SQL Azureの既存の主キーを変更するにはどうすればよいですか?


25

SQL Azureテーブルの既存のプライマリキーを変更したい。
現在、1つの列があり、別の列を追加したいと思います。

さて、SQL Server 2008では、これは簡単なことでした。SSMSでやっただけです。できた これは、SQL Serverからスクリプトを作成した場合のPKの外観です。

ALTER TABLE [dbo].[Friend] ADD  CONSTRAINT [PK_Friend] PRIMARY KEY CLUSTERED 
(
  [UserId] ASC,
  [Id] ASC
)

ただし、SQL Azureでは、上記を実行しようとすると、もちろん失敗します。

Table 'Friend' already has a primary key defined on it.

結構です、私はキーを落とそうとします:

Tables without a clustered index are not supported in this version of SQL Server. Please create a clustered index and try again.

それでは、PKを削除するために一時的なクラスター化インデックスを作成しようとしています。

CREATE CLUSTERED INDEX IX_Test ON [Friend] ([UserId],[Id])

結果: Cannot create more than one clustered index on table 'Friend'. Drop the existing clustered index 'PK_Friend' before creating another.

素晴らしい、catch22の瞬間。

UserId列を既存のPKに追加するにはどうすればよいですか?


回答:


34

注: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アプローチにはいくつかの問題があります。最も重要なことは、名前の変更中にテーブルのアクセス許可が引き継がれないことと、外部キーの制約です。


私の場合、A1〜A4は回答なしです。私のIDはID列ではありませんが、A5はトリックを行いました。
マグナス

sp_renameの回避策は役に立ちました!
ジャスティン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.