it-swarm-id.com

Bagaimana saya bisa mengubah Kunci Utama yang ada pada SQL Azure?

Saya ingin memodifikasi kunci utama yang ada pada tabel SQL Azure.
Saat ini memiliki satu kolom, dan saya ingin menambahkan yang lain.

Sekarang, pada SQL Server 2008 ini adalah sepotong kue, lakukan saja di SSMS, poof. Selesai Ini adalah bagaimana PK terlihat jika saya skrip dari SQL Server:

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

Namun, pada SQL Azure, ketika saya mencoba mengeksekusi di atas, tentu saja akan gagal:

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

Baik, jadi saya mencoba untuk menjatuhkan kunci:

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

Oke, jadi saya mencoba membuat indeks cluster sementara untuk menjatuhkan PK:

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

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

Hebat, momen yang menarik.

Bagaimana cara menambahkan kolom UserId ke PK saya yang ada?

25
Magnus

Catatan: pada Azure SQL Database v12, pembatasan ini tidak lagi berlaku.

Tidak ada yang namanya 'indeks primer'. Ada yang namanya 'primary key' dan ada juga yang namanya 'clustered index'. Konsep yang berbeda, sering membingungkan. Dengan mengingat perbedaan ini, mari kita kembali ke pertanyaan:

T1) Dapatkah indeks berkerumun di tabel SQL Azure diubah?
A: Ya. Gunakan 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

T2) Dapatkah indeks berkerumun dari tabel yang memiliki batasan kunci primer diubah?
A: Ya, sama seperti di atas, selama batasan kunci primer tidak ditegakkan melalui indeks berkerumun:

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

T3) Dapatkah batasan kunci utama dari tabel diubah?
A: Ya, selama kendala utama tidak ditegakkan melalui indeks berkerumun:

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

T4) Dapatkah kunci utama tabel diubah ketika diberlakukan melalui indeks berkerumun?
A: Ya, jika meja tidak memiliki baris:

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

T5) Dapatkah kunci primer tabel diubah ketika diberlakukan melalui indeks berkerumun jika tabel diisi?
A: Tidak. Operasi apa pun yang mengubah indeks pengelompokan yang terisi menjadi tumpukan akan diblokir dalam SQL Azure, bahkan jika tabelnya kosong :

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;

Sebagai catatan tambahan: batasan dapat diubah jika tabelnya terpotong .

Solusi untuk mengubah batasan PK dari tabel berpopulasi adalah melakukan yang lama yang baik sp_rename trik:

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 Pendekatan memiliki beberapa masalah, yang paling penting adalah bahwa izin di atas meja tidak terbawa selama penggantian nama, serta kendala kunci asing.

34
Remus Rusanu