Nota: a partir do Banco de Dados SQL do Azure v12, essas restrições não se aplicam mais.
O "índice primário" não existe. Existe uma "chave primária" e também um "índice de cluster". Conceitos distintos, frequentemente confusos. Com essa distinção em mente, vamos revisitar a questão:
Q1) O índice clusterizado em uma tabela do SQL Azure pode ser modificado?
A: sim Use 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) O índice clusterizado de uma tabela que possui uma restrição de chave primária pode ser modificado?
R: Sim, o mesmo que acima, desde que a restrição de chave primária não seja imposta pelo índice clusterizado:
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
Q3) A restrição de chave primária de uma tabela pode ser modificada?
R: Sim, desde que a restrição principal não seja imposta pelo índice clusterizado:
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
Q4) A chave primária de uma tabela pode ser modificada quando aplicada pelo índice de cluster?
A: Sim, se a tabela nunca teve nenhuma linha:
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
Q5) A chave primária de uma tabela pode ser modificada quando aplicada pelo índice de cluster se a tabela for preenchida?
R: Não. Qualquer operação que converta um índice clusterizado preenchido em um heap será bloqueada no SQL Azure, mesmo se a tabela estiver vazia :
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;
Como observação lateral: a restrição pode ser modificada se a tabela estiver truncada .
A solução alternativa para alterar a restrição PK de uma tabela preenchida é fazer o bom e velho sp_rename
truque:
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';
A sp_rename
abordagem tem alguns problemas, o mais importante é que as permissões na tabela não são transferidas durante a renomeação, além de restrições de chave estrangeira.