注:Azure SQL Database v12以降、これらの制限は適用されなくなりました。
これは「プライマリインデックス」のようなものではありません。「主キー」のようなものがあり、「クラスター化インデックス」のようなものもあります。しばしば混同される、明確な概念。この区別を念頭に置いて、質問を再考してみましょう。
Q1)SQL Azureテーブルのクラスター化インデックスを変更できますか?
A:はい。使用 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)主キー制約を持つテーブルのクラスター化インデックスを変更できますか?
A:はい、上記と同じ、クラスター化インデックスを介して主キー制約が適用されない限り:
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:はい、クラスター化インデックスを介して主な制約が適用されない限り:
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:はい、テーブルに行がなかった場合:
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:いいえ。入力されたクラスター化インデックスをヒープに変換する操作は、テーブルが空であっても 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
アプローチにはいくつかの問題があります。最も重要なことは、名前の変更中にテーブルのアクセス許可が引き継がれないことと、外部キーの制約です。