2011-11-22 33 views
76

Chúng tôi có một bảng 5GB (gần 500 triệu hàng) và chúng tôi muốn loại bỏ thuộc tính nhận dạng trên một cột, nhưng khi chúng tôi cố gắng thực hiện điều này thông qua SSMS - nó hết giờ.Xóa danh tính từ một cột trong một bảng

Điều này có thể được thực hiện thông qua T-SQL không?

+0

Bạn có thể đăng giản đồ của bảng tại đây không? –

+0

Tôi chắc chắn có những lý do tuyệt vời mà SQL Server không hỗ trợ loại bỏ một đặc tính nhận dạng từ một cột thông qua một câu lệnh ALTER TABLE ... nhưng nó vẫn làm tôi buồn vì đó là trường hợp. –

Trả lời

95

Bạn không thể xóa thông số IDENTITY sau khi đã đặt.

Để loại bỏ toàn bộ cột:

ALTER TABLE yourTable 
DROP COLUMN yourCOlumn; 

Thông tin về ALTER TABLE đây

Nếu bạn cần phải giữ cho dữ liệu, nhưng loại bỏ các cột IDENTITY, bạn sẽ cần phải:

  • Tạo cột mới
  • Chuyển dữ liệu từ cột IDENTITY hiện tại t o cột mới
  • Thả cột IDENTITY hiện tại.
  • Đổi tên cột mới với tên cột gốc
+3

bạn có thể xóa thông số nhận dạng. Trong thực tế, tôi đã phải làm điều đó ngày hôm qua bằng cách sử dụng SSMS mặc dù không phải trên 500 triệu hàng. – Simon

+20

@simon nếu bạn thực hiện các thay đổi của mình, bạn sẽ thấy SSMS thực sự đang tạo bản sao của bảng w/o thuộc tính nhận dạng. –

+3

Tôi chỉ muốn thêm để đổi tên cột mới thành tên của cột ban đầu. Ngoài ra, nếu cột 'identity' này được sử dụng như một phần của' khóa ngoài' trong một bảng khác, bạn sẽ phải loại bỏ các ràng buộc đầu tiên, sau đó thực hiện hành động như @AdamWenger được đề cập về việc loại bỏ danh tính 'thuộc tính/thuộc tính' ..Bạn cũng có thể xem liên kết này để biết thêm chi tiết về cách xóa thuộc tính chỉ: http://blog.sqlauthority.com/2009/05/03/sql-server-add-or-remove-identity-property-on- cột/.. Chúc may mắn! – Nonym

46

này bị lộn xộn với ràng buộc khoá ngoại và tiểu học, vì vậy đây là một số kịch bản để giúp bạn trên con đường của bạn:

Đầu tiên, tạo một cột trùng lặp với một tên tạm thời:

alter table yourTable add tempId int NOT NULL default -1; 
update yourTable set tempId = id; 

Tiếp theo, lấy tên của ràng buộc khoá chính của bạn:

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'yourTable'; 

Bây giờ hãy thử thả các ràng buộc khoá chính cho cột của bạn:

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id; 

Nếu bạn có các phím nước ngoài, nó sẽ thất bại, vì vậy nếu để thả các ràng buộc khoá ngoại. GIỮ THEO D WHI ĐỂ B TNG BẠN CHẠY NÀY CHO BẠN CÓ THỂ THÊM CÁC CẤU TRÚC LẠI TRÊN LATER !!!

SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'otherTable'; 
alter table otherTable drop constraint fk_otherTable_yourTable; 
commit; 
.. 

Khi tất cả ràng buộc khoá ngoại của bạn đã được gỡ bỏ, bạn sẽ có thể để loại bỏ các hạn chế PK, thả cột đó, đổi tên cột temp của bạn, và thêm các hạn chế PK để cột rằng:

ALTER TABLE yourTable DROP CONSTRAINT PK_yourTable_id; 
alter table yourTable drop column id; 
EXEC sp_rename 'yourTable.tempId', 'id', 'COLUMN'; 
ALTER TABLE yourTable ADD CONSTRAINT PK_yourTable_id PRIMARY KEY (id) 
commit; 

Cuối cùng, thêm những hạn chế FK lại:

alter table otherTable add constraint fk_otherTable_yourTable foreign key (yourTable_id) references yourTable(id); 
.. 

El Fin!

+0

chú ý đến phiên bản máy chủ sql của bạn, tôi đã thử trong máy chủ sql Azure, không phải tất cả các hoạt động ở đây đều được hỗ trợ trong phiên bản Azure sql. – dasons

+0

Cảm ơn bạn đã trả lời! Giúp tôi rất nhiều! Bạn chỉ cần thêm xác minh cho các chỉ mục tham chiếu cột. Một cái gì đó như: 'Chọn t.name 'Bảng', i.name 'Index', c.name 'Cột', \t i.is_primary_key, \t i.is_unique Từ sys.tables t Nội Tham gia sys.indexes i Trên i.object_id = t.object_id Tham gia bên trong sys.index_columns ic ON ic.object_id = i.object_id Và i.index_id = ic.index_id Tham gia bên trong sys.columns c ON ic.object_id = c. object_id và ic.column_id = c.column_id Nơi t.name = 'tableName' Đặt hàng theo t.name, i.name, i.index_id, ic.index_column_id' –

+0

mẹo tốt, giúp tôi rất nhiều, Nhưng một điểm, tôi muốn đề cập ở đây là, Khi chúng ta thêm một cột mới trùng lặp như đã đề cập ở bước 1, nó được thêm vào cuối nhưng nói chung chúng ta muốn rằng Id là cột đầu tiên trong bảng đó. Vậy có cách giải quyết nào khác không? –

40

Nếu bạn muốn làm điều này mà không cần thêm và Populating một cột mới, mà không cần sắp xếp lại các cộtvới hầu như không có thời gian chết vì không có dữ liệu đang thay đổi trên bàn, chúng ta hãy làm một số ma thuật với chức năng phân vùng (nhưng vì không có phân vùng được sử dụng bạn không cần phiên bản Enterprise):

  1. Hủy bỏ tất cả các phím nước ngoài trỏ đến bảng này
  2. Script bảng được tạo ra; đổi tên mọi thứ, v.d. 'MyTable2', 'MyIndex2', v.v. Xóa đặc tả IDENTITY.
  3. Bây giờ bạn sẽ có hai bảng "giống hệt", một bảng đầy đủ, cái còn lại trống rỗng không có IDENTITY.
  4. Chạy ALTER TABLE [Original] SWITCH TO [Original2]
  5. Bây giờ bảng ban đầu của bạn sẽ trống và bảng mới sẽ có dữ liệu. Bạn đã chuyển siêu dữ liệu cho hai bảng (tức thì).
  6. Thả bản gốc (bảng trống bây giờ), exec sys.sp_rename để đổi tên các đối tượng lược đồ khác nhau về tên gốc và sau đó bạn có thể tạo lại khóa ngoài của mình.

Ví dụ, đưa ra:

CREATE TABLE Original 
(
    Id INT IDENTITY PRIMARY KEY 
, Value NVARCHAR(300) 
); 
CREATE NONCLUSTERED INDEX IX_Original_Value ON Original (Value); 

INSERT INTO Original 
SELECT 'abcd' 
UNION ALL 
SELECT 'defg'; 

Bạn có thể làm như sau:

--create new table with no IDENTITY 
CREATE TABLE Original2 
(
    Id INT PRIMARY KEY 
, Value NVARCHAR(300) 
); 
CREATE NONCLUSTERED INDEX IX_Original_Value2 ON Original2 (Value); 

--data before switch 
SELECT 'Original', * 
FROM Original 
UNION ALL 
SELECT 'Original2', * 
FROM Original2; 

ALTER TABLE Original SWITCH TO Original2; 

--data after switch 
SELECT 'Original', * 
FROM Original 
UNION ALL 
SELECT 'Original2', * 
FROM Original2; 

--clean up 
DROP TABLE Original; 
EXEC sys.sp_rename 'Original2.IX_Original_Value2', 'IX_Original_Value', 'INDEX'; 
EXEC sys.sp_rename 'Original2', 'Original', 'OBJECT'; 


UPDATE Original 
SET Id = Id + 1; 

SELECT * 
FROM Original; 
+0

Tôi không có thời gian để thực sự cố gắng này, nhưng nó là một điều tốt để biết thời gian tiếp theo tôi thực sự cần phải thả một bản sắc. – CoderDennis

+5

Đây phải là câu trả lời được chấp nhận. Đó là cách duy nhất để loại bỏ cột nhận dạng mà không cần di chuyển dữ liệu lớn. – Vaccano

+0

Wow! Điều này rất thông minh. –

11

Tôi chỉ có vấn đề này như vậy. 4 câu lệnh trong SSMS thay vì sử dụng GUI và nó rất nhanh.

  • Thực hiện một cột mới

    alter table users add newusernum int;

  • Sao chép giá trị trên

    update users set newusernum=usernum;

  • Drop cột cũ

    alter table users drop column usernum;

  • Đổi tên cột mới với tên cột cũ

    EXEC sp_RENAME 'users.newusernum' , 'usernum', 'COLUMN';

7

Tiếp theo kịch bản loại bỏ lĩnh vực nhận dạng cho một cột có tên 'Id'

Hy vọng nó giúp.

BEGIN TRAN 
BEGIN TRY 
    EXEC sp_rename '[SomeTable].[Id]', 'OldId'; 

    ALTER TABLE [SomeTable] ADD Id int NULL 

    EXEC ('UPDATE [SomeTable] SET Id = OldId') 

    ALTER TABLE [SomeTable] NOCHECK CONSTRAINT ALL 

    ALTER TABLE [SomeTable] DROP CONSTRAINT [PK_constraintName]; 
    ALTER TABLE [SomeTable] DROP COLUMN OldId 
    ALTER TABLE [SomeTable] ALTER COLUMN [Id] INTEGER NOT NULL 
    ALTER TABLE [SomeTable] ADD CONSTRAINT PK_JobInfo PRIMARY KEY (Id) 

    ALTER TABLE [SomeTable] CHECK CONSTRAINT ALL 

    COMMIT TRAN 
END TRY 
BEGIN CATCH 
    ROLLBACK TRAN 
    SELECT ERROR_MESSAGE() 
END CATCH 
1

Mã dưới đây hoạt động tốt, khi chúng tôi không biết tên cột nhận dạng.

và muốn sao chép dữ liệu vào bảng tạm thời mới như Invoice_DELETED. và lần sau chúng tôi sử dụng: chèn vào Invoice_DELETED chọn * từ Hóa đơn, trong đó ...

SELECT t1.* 
INTO Invoice_DELETED 
FROM Invoice t1 
LEFT JOIN Invoice ON 1 = 0 
--WHERE t1.InvoiceID = @InvoiceID 

đặc biệt nhờ 'Andriy M'

cho lời giải thích xem chi tiết: https://dba.stackexchange.com/a/138345/101038

0

Chỉ cần cho một ai đó có cùng một vấn đề tôi đã làm. Nếu bạn chỉ muốn thực hiện một số chèn chỉ một khi bạn có thể làm một cái gì đó như thế này.

Hãy giả sử bạn có một bảng với hai cột

ID Identity (1,1) | Name Varchar 

và muốn chèn một hàng với ID = 4. Vì vậy, bạn gieo hạt nó tới 3 vậy trong lần sau là 4

DBCC CHECKIDENT([YourTable], RESEED, 3) 

Tận dụng tối Chèn

INSERT INTO [YourTable] 
     (Name) 
VALUES ('Client') 

Và có được hạt giống của bạn trở lại ID cao nhất, cho phép giả sử là 15

DBCC CHECKIDENT([YourTable], RESEED, 15) 

Xong!

Các vấn đề liên quan