Làm cách nào tôi có thể thay đổi Khóa chính hiện có trên SQL Azure?


25

Tôi muốn sửa đổi khóa chính hiện có trên bảng SQL Azure.
Nó hiện có một cột và tôi muốn thêm một cột khác.

Bây giờ, trên SQL Server 2008, đây là một miếng bánh, chỉ cần thực hiện trong SSMS, gặp sự cố. Làm xong. Đây là cách PK trông như thế nào nếu tôi script nó từ SQL Server:

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

Tuy nhiên, trên SQL Azure, khi tôi cố gắng thực hiện các thao tác trên, tất nhiên nó sẽ thất bại:

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

Tốt, vì vậy tôi cố gắng thả chìa khóa:

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

Ok, vì vậy tôi cố gắng tạo một chỉ mục cụm tạm thời để bỏ PK:

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

Kết quả nào trong: Cannot create more than one clustered index on table 'Friend'. Drop the existing clustered index 'PK_Friend' before creating another.

Tuyệt vời, một khoảnh khắc Catch22.

Làm cách nào để thêm cột UserId vào PK hiện tại của tôi?


Câu trả lời:


34

Lưu ý: kể từ Azure SQL Database v12, những hạn chế này không còn được áp dụng.

Đây không phải là một "chỉ số chính". Có một thứ gọi là 'khóa chính' và cũng có một thứ gọi là 'chỉ số cụm'. Khái niệm khác biệt, thường bị nhầm lẫn. Với sự khác biệt này trong tâm trí, hãy xem xét lại câu hỏi:

Q1) Chỉ mục cụm trong bảng SQL Azure có thể được sửa đổi không?
A: Vâng. Sử dụng 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

Câu 2) Có thể sửa đổi chỉ mục cụm của bảng có ràng buộc khóa chính không?
Trả lời: Có, giống như trên, miễn là ràng buộc khóa chính không được thi hành thông qua chỉ mục được nhóm:

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

Câu 3) Có thể sửa đổi ràng buộc khóa chính của bảng không?
Trả lời: Có, miễn là ràng buộc chính không được thi hành thông qua chỉ mục được nhóm:

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

Câu hỏi 4) Khóa chính của bảng có thể được sửa đổi khi được thi hành thông qua chỉ mục được nhóm không?
A: Có, nếu bảng không bao giờ có bất kỳ hàng nào:

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

Câu 5) Khóa chính của bảng có thể được sửa đổi khi được thi hành thông qua chỉ mục được nhóm nếu bảng được điền không?
Trả lời: Không. Bất kỳ thao tác nào chuyển đổi một chỉ mục được nhóm thành dân số thành một đống sẽ bị chặn trong SQL Azure, ngay cả khi bảng trống :

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;

Như một lưu ý phụ: ràng buộc có thể được sửa đổi nếu bảng bị cắt ngắn .

Cách giải quyết để thay đổi ràng buộc PK của bảng dân cư là thực hiện sp_renamethủ thuật cũ tốt :

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';

Cách sp_renametiếp cận có một số vấn đề, quan trọng nhất là các quyền trên bảng không được thực hiện trong quá trình đổi tên, cũng như các ràng buộc khóa ngoài.


A1-A4 là không có câu trả lời trong trường hợp của tôi. A5 đã lừa, mặc dù Id của tôi không phải là cột nhận dạng.
Magnus

cách giải quyết sp_rename rất hữu ích!
Justin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.