Uwaga: od wersji 12 bazy danych SQL Azure te ograniczenia nie mają już zastosowania.
Nie ma czegoś takiego jak „indeks główny”. Istnieje coś takiego jak „klucz podstawowy”, a także coś takiego jak „indeks klastrowany”. Odrębne koncepcje, często mylone. Mając na uwadze to rozróżnienie, powróćmy do pytania:
P1) Czy można zmodyfikować indeks klastrowany w tabeli SQL Azure?
Odp .: Tak. Użyj WITH (DROP_EXISTING=ON)
:
create table Friend (
UserId int not null,
Id int not null);
go
create clustered index cdxFriend on Friend (UserId, Id);
go
create clustered index cdxFriend on Friend (Id, UserId) with (drop_existing=on);
go
Q2) Czy można zmodyfikować indeks klastrowy tabeli z ograniczeniem klucza podstawowego?
Odp .: Tak, tak jak powyżej, o ile ograniczenie klucza podstawowego nie jest wymuszane przez indeks klastrowany:
create table Friend (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend primary key nonclustered (Id));
create clustered index cdxFriend on Friend (UserId, Id);
go
create clustered index cdxFriend on Friend (Id, UserId) with (drop_existing=on);
go
P3) Czy można zmodyfikować ograniczenie klucza podstawowego tabeli?
Odp .: Tak, dopóki podstawowe ograniczenie nie jest wymuszane przez indeks klastrowany:
create table Friend (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend primary key nonclustered (Id));
go
create clustered index cdxFriend on Friend (UserId, Id);
go
alter table Friend drop constraint pk_Friend;
alter table Friend add constraint pk_Friend primary key nonclustered (UserId)
go
P4) Czy klucz podstawowy tabeli można modyfikować, gdy jest egzekwowany przez indeks klastrowany?
Odp .: Tak, jeśli tabela nigdy nie miała żadnych wierszy:
create table Friend (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend primary key clustered (UserId, Id));
go
alter table Friend drop constraint pk_Friend;
alter table Friend add constraint pk_Friend primary key clustered (Id, UserId)
go
P5) Czy klucz podstawowy tabeli można modyfikować, gdy jest wymuszany przez indeks klastrowany, jeśli tabela jest zapełniona?
Odp .: Nie. Każda operacja, która konwertuje zapełniony indeks klastrowany na stertę, zostanie zablokowana na SQL Azure, nawet jeśli tabela jest pusta :
create table Friend (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend primary key clustered (UserId, Id));
go
insert into Friend (UserId) values (1);
delete from Friend;
go
alter table Friend drop constraint pk_Friend;
Na marginesie: ograniczenie można zmodyfikować, jeśli tabela zostanie obcięta .
Obejściem problemu zmiany ograniczenia PK w zapełnionej tabeli jest wykonanie starej dobrej sp_rename
sztuczki:
create table Friend (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend primary key clustered (UserId, Id));
go
insert into Friend (UserId) values (1);
go
create table FriendNew (
UserId int not null,
Id int not null identity(1,1),
constraint pk_Friend_New primary key clustered (Id, UserId));
go
set identity_insert FriendNew on;
insert into FriendNew (UserId, Id)
select UserId, Id
from Friend;
set identity_insert FriendNew off;
go
begin transaction
exec sp_rename 'Friend', 'FriendOld';
exec sp_rename 'FriendNew', 'Friend';
commit;
go
sp_help 'Friend';
sp_rename
Podejście ma pewne problemy, najważniejsze jest, że uprawnienia na stole nie przenoszą w czasie zmiany nazwy, a także ograniczenia klucz obcy.