注意:从Azure SQL数据库v12开始,这些限制不再适用。
根本没有所谓的“主索引”。有“主键”之类的东西,也有“聚集索引”之类的东西。截然不同的概念,通常令人困惑。考虑到这种区别,让我们重温这个问题:
Q1)可以修改SQL Azure表中的聚集索引吗?
答:是的。用途 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)可以修改具有主键约束的表的聚集索引吗?
答:是的,与上面相同,只要不通过聚簇索引强制执行主键约束:
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)可以修改表的主键约束吗?
答:是的,只要不通过聚集索引强制执行主要约束:
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)通过聚簇索引强制执行时,可以修改表的主键吗?
答:是的,如果表从未有任何行:
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)如果通过表的聚集键强制执行表的主键,是否可以对其进行修改?
答:不能。任何将填充的聚集索引转换为堆的操作都将在SQL Azure中被阻止,即使表为空:
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;
附带说明:如果表被截断,则可以修改约束。
更改已填充表的PK约束的解决方法是做一个很好的老sp_rename
技巧:
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
方法存在一些问题,最重要的是,表的权限在重命名期间不会保留,以及外键约束。