Tại sao xóa thuộc tính Danh tính trên một cột không được hỗ trợ


11

Tôi đã đọc rằng sau SQL Server 2000, khả năng "hủy nhận dạng" một cột danh tính đã bị xóa. Và đó là "Theo thiết kế" (không chỉ là một tính năng còn thiếu).

Đây là một ví dụ tôi tìm thấy trên một blog . Nó liên quan đến việc cập nhật các bảng hệ thống. (Và khả năng đó đã bị loại bỏ sau SQL Server 2000.) Tôi hiểu rằng làm điều này thông qua các bảng hệ thống không phải là một ý tưởng hay. Tôi chỉ tự hỏi tại sao một tính năng để làm điều này theo cách khác không phải là xung quanh.

Làm việc xung quanh điều này sẽ gây cho tôi một lượng công việc đáng kể. (Sao chép nhiều hàng trăm triệu hàng vào các bảng mới trong môi trường không dung nạp thời gian chết.)

Vì vậy, tôi nghĩ rằng tôi sẽ hỏi "Tại sao".

Điều gì đã thay đổi trong Sql Server 2005 và các phiên bản mới hơn khiến điều này trở thành một điều tồi tệ? Hay nó luôn luôn xấu, và chỉ không bị khóa?

"Thực hành tốt nhất" (hoặc nguyên tắc tương tự) nào sẽ bị vi phạm bằng cách biến cột nhận dạng thành cột bình thường trở lại?

-

Cập nhật để trả lời yêu cầu "tại sao tôi làm việc này":
Đây là một bản tóm tắt cấp độ rất cao: Tôi sẽ bắt đầu thêm các phân vùng vào các bảng của mình. (Để tôi có thể lưu trữ / lọc dữ liệu cũ.) Điều đó thật dễ dàng. Nhưng đôi khi tôi cần di chuyển một bản ghi sang một phân vùng khác để nó không bị xóa (khi một phân vùng xuất hiện để lưu trữ / xóa). (Tôi có cột phân vùng tăng 2 lần để luôn có khoảng trống để di chuyển hàng sang phân vùng khác.)

Nhưng nếu cột phân vùng là cột định danh, thì tôi phải xóa và chèn lại giá trị (không có cách nào để cập nhật giá trị của cột nhận dạng). Mà gây ra vấn đề với nhân rộng.

Vì vậy, tôi muốn sử dụng một chuỗi thay vì một cột danh tính. Nhưng chuyển đổi đó là rất rất khó khăn trên cơ sở dữ liệu lớn.

Câu trả lời:


22

Câu hỏi của bạn là, về cơ bản:

Tại sao tôi không còn có thể làm điều rủi ro này mà tôi không bao giờ được phép làm ở nơi đầu tiên?

Câu trả lời cho câu hỏi đó phần lớn không liên quan (mặc dù bạn có thể thấy một số nhận xét của Microsoft trong các mục Kết nối này yêu cầu chức năng này: # 294193# 252226). Để đầy đủ, tóm tắt của tôi là: Khả năng loại bỏ thuộc tính nhận dạng là một tác dụng phụ ngoài ý muốn của việc có khả năng gây rối với các bảng hệ thống ở vị trí đầu tiên. Điều này không có ý định được sử dụng theo nhiều cách mà nó thường gây ra hậu quả rất xấu và do đó nó đã bị xóa. Đó là một hack bảng hệ thống không có giấy tờ, không được hỗ trợ. Khả năng thay đổi dữ liệu trong các bảng hệ thống không bị xóa vì Microsoft không còn muốn bạn hack theo cách của một cột là một cột định danh, nó đã bị xóa vì mucking với các bảng hệ thống là vô cùng rủi ro. Xóa chính thuộc tính IDENTITY không phải là loại bỏ tính năng được nhắm mục tiêu cụ thể và tôi sẽ không bao giờ tin tưởng hoàn toàn vào phương pháp này ngay cả khi trở lại thời cổ đại khi có thể.

Điều đó nói rằng, làm thế nào về chúng ta trả lời câu hỏi này thay thế?

Làm cách nào để xóa thuộc tính IDENTITY của cột với mức tối thiểu hoặc không có thời gian chết?

Điều này bạn có thể thực hiện dễ dàng, bằng cách sử dụng ALTER TABLE ... SWITCHmột kỹ thuật mà tôi chắc chắn là lần đầu tiên tôi học được từ Paul White của chúng tôi trong các cách giải quyết cho Connect # 252226 . Ví dụ nhanh, đưa ra bảng đơn giản này:

CREATE TABLE dbo.Original
(
  ID INT IDENTITY(1,1) PRIMARY KEY,
  name SYSNAME
);
GO

INSERT dbo.Original(name) VALUES(N'foo'),(N'bar');
GO

SELECT * FROM dbo.Original;
GO

Các kết quả:

ID  name
--  ----
1   foo
2   bar

Bây giờ, hãy tạo một bảng bóng và chuyển sang bảng đó, sau đó thả bảng cũ, đổi tên bảng mới và sau đó tiếp tục hoạt động bình thường:

CREATE TABLE dbo.New
(
  ID INT PRIMARY KEY,
  name SYSNAME
);
GO

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
  ALTER TABLE dbo.Original SWITCH TO dbo.New;
  DROP TABLE dbo.Original;
  EXEC sys.sp_rename N'dbo.New', N'Original', 'OBJECT';
COMMIT TRANSACTION;
GO

INSERT dbo.Original(ID,name) VALUES(3,N'splunge');
UPDATE dbo.Original SET ID = 6 WHERE ID = 1;
GO

SELECT * FROM dbo.Original;
GO

Các kết quả:

ID  name
--  -------
2   bar
3   splunge
6   foo

Bây giờ dọn dẹp:

DROP TABLE dbo.Original;

Đây chỉ là một hoạt động siêu dữ liệu, không có chuyển động dữ liệu và sẽ chỉ chặn những người dùng khác trong khi siêu dữ liệu đang được cập nhật. Nhưng, thừa nhận, đó là một ví dụ rất đơn giản. Nếu bạn có khóa ngoại hoặc đang sử dụng các tính năng khác như sao chép, Thay đổi dữ liệu, Theo dõi thay đổi, v.v., bạn có thể cần phải tắt hoặc xóa một số tính năng đó trước khi thực hiện thay đổi này (Tôi đã thử nghiệm tất cả các kết hợp). Đối với các khóa ngoại cụ thể, hãy xem mẹo này cho biết cách tạo tập lệnh để thả và tạo lại tất cả (hoặc đã chọn) các ràng buộc khóa ngoài.

Ngoài ra, bạn sẽ cần cập nhật mã ứng dụng của mình để không mong đợi SQL Server điền vào cột này và kiểm tra bất kỳ câu lệnh chèn hoặc chọn nào có thể tùy thuộc vào thứ tự cột hoặc cột mà chúng cần chỉ định. Nói chung, tôi sẽ grep toàn bộ cơ sở mã của bạn cho bất kỳ đề cập đến bảng này.

Cũng xem kịch bản này từ Itzik Ben-Gan (nguồn: bài viết cổ này ) để biết cách khác để xử lý vấn đề này, nhưng có chuyển động dữ liệu liên quan ở đây, vì vậy nó không cung cấp theo yêu cầu "không có hoặc thời gian chết tối thiểu".


3
Tôi muốn khuyến khích bất cứ ai đến để nâng cấp hai mục kết nối. Làm thế nào khó có thể thực hiện một tính năng ALTER COLUMN để bật hoặc tắt boolean danh tính?! Đau đớn để làm việc xung quanh.
usr

Tôi phải thừa nhận, vì một số lý do tôi nghĩ rằng ..SWITCH..chỉ hoạt động cho các bảng có ít nhất một phân vùng được xác định.
RBarryYoung

Chỉ muốn thêm mà SWITCHkhông yêu cầu Phiên bản doanh nghiệp, mặc dù phân vùng bảng có.
Dan Guzman
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.