2009-01-23 25 views
50

Tôi đang sử dụng mã này để thiết lập lại bản sắc trên một bảng:DBCC CHECKIDENT Thiết lập nhận dạng 0

DBCC CHECKIDENT('TableName', RESEED, 0) 

này hoạt động tốt hầu hết thời gian, với sự chèn đầu tiên tôi chèn 1 vào cột Id . Tuy nhiên nếu tôi thả db và tạo lại nó (sử dụng kịch bản tôi đã viết) và sau đó gọi DBCC CHECKIDENT, mục đầu tiên được chèn sẽ có ID là 0.

Bất kỳ ý tưởng nào?

EDIT: Sau khi nghiên cứu tôi phát hiện ra tôi đã không đọc các tài liệu hướng dẫn đúng cách:. http://msdn.microsoft.com/en-us/library/aa258817(SQL.80).aspx - "Giá trị bản sắc hiện tại được thiết lập để các new_reseed_value Nếu không có hàng đã được đưa lên bàn vì nó được tạo ra, hàng đầu tiên chèn sau khi thực hiện DBCC CHECKIDENT sẽ sử dụng new_reseed_value như danh tánh. Nếu không, hàng tiếp theo sẽ sử dụng chèn new_reseed_value + 1. "

Trả lời

17

Như bạn đã chỉ ra trong câu hỏi của mình là documented behavior. Dù vậy tôi vẫn thấy nó lạ. Tôi sử dụng để repopulate cơ sở dữ liệu thử nghiệm và mặc dù tôi không dựa vào các giá trị của các lĩnh vực nhận dạng nó là một chút khó chịu để có giá trị khác nhau khi populating cơ sở dữ liệu cho lần đầu tiên từ đầu và sau khi loại bỏ tất cả dữ liệu và populating một lần nữa.

Một giải pháp có thể là sử dụng cắt ngắn để làm sạch bảng thay vì xóa. Nhưng sau đó bạn cần phải thả tất cả các ràng buộc và tạo lại chúng sau

Bằng cách đó, nó luôn hoạt động như một bảng mới được tạo ra và không cần phải gọi DBCC CHECKIDENT. Giá trị bản sắc đầu tiên sẽ là một quy định trong định nghĩa bảng và nó sẽ giống nhau không có vấn đề nếu bạn chèn dữ liệu cho lần đầu tiên hoặc cho N-thứ

+1

liên kết đó dường như bị chết, tài liệu hiện tại https://msdn.microsoft.com/en-us/library/ms176057.aspx, nói rằng đó chỉ là hành vi mong đợi cho các phiên bản trước năm 2012, nhưng điều đó dường như không đúng (thử nghiệm trên phiên bản 2012, khả năng tương thích được đặt thành năm 2012, vẫn gặp sự cố). – jmoreno

5

Thay đổi tuyên bố

DBCC CHECKIDENT('TableName', RESEED, 1) 

này sẽ bắt đầu từ 2 (hoặc 1 whe n bạn tạo lại bảng), nhưng nó sẽ không bao giờ là 0.

42

Bạn thích hợp với nội dung bạn viết trong bản chỉnh sửa câu hỏi.

Sau khi chạy DBCC CHECKIDENT('TableName', RESEED, 0):
- bảng mới được tạo sẽ bắt đầu với bản sắc 0
- bảng hiện tại sẽ tiếp tục đậm đà bản sắc 1

Giải pháp là trong kịch bản dưới đây, đó là sắp xếp của một người nghèo-mans-truncate :)

-- Remove all records from the Table 
DELETE FROM TableName 

-- Use sys.identity_columns to see if there was a last known identity value 
-- for the Table. If there was one, the Table is not new and needs a reset 
IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'TableName' AND last_value IS NOT NULL) 
    DBCC CHECKIDENT (TableName, RESEED, 0); 
+1

Rất tốt nhưng khi giao dịch với nhiều lược đồ, bạn có thể muốn điều chỉnh một chút để khớp với 'object_id' thay vì sử dụng' OBJECT_NAME() 'để tra cứu tên bảng:' IF EXISTS (SELECT * FROM sys.identity_columns WHERE object_id = OBJECT_ID ('Schema.TableName') VÀ last_value IS NOT NULL') – Nick

1

Tôi đã làm điều này làm thử nghiệm để đặt lại giá trị thành 0 vì tôi muốn cột nhận dạng đầu tiên của tôi bằng 0 và nó hoạt động.

dbcc CHECKIDENT(MOVIE,RESEED,0) 
dbcc CHECKIDENT(MOVIE,RESEED,-1) 
DBCC CHECKIDENT(MOVIE,NORESEED) 
1
USE AdventureWorks2012; 
GO 
DBCC CHECKIDENT ('Person.AddressType', RESEED, 0); 
GO 



AdventureWorks2012=Your databasename 
Person.AddressType=Your tablename 
1

Tôi đã sử dụng điều này trong SQL để thiết SẮC đến một giá trị cụ thể: -

DECLARE @ID int = 42; 
DECLARE @TABLENAME varchar(50) = 'tablename' 

DECLARE @SQL nvarchar(1000) = 'IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '''[email protected]+''' AND last_value IS NOT NULL) 
    BEGIN 
     DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID-1)+'); 
    END 
    ELSE 
    BEGIN 
     DBCC CHECKIDENT('[email protected]+', RESEED,' + CONVERT(VARCHAR(10),@ID)+'); 
    END'; 
EXEC (@SQL); 

Và điều này trong C# để thiết lập một giá trị cụ thể: -

SetIdentity(context, "tablename", 42); 
. 
. 
private static void SetIdentity(DbContext context, string table,int id) 
{ 
    string str = "IF EXISTS (SELECT * FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = '" + table 
     + "' AND last_value IS NOT NULL)\nBEGIN\n"; 
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id - 1).ToString() + ");\n"; 
    str += "END\nELSE\nBEGIN\n"; 
    str += "DBCC CHECKIDENT('" + table + "', RESEED," + (id).ToString() + ");\n"; 
    str += "END\n"; 
    context.Database.ExecuteSqlCommand(str); 
} 

Điều này xây dựng trên các câu trả lời ở trên và luôn đảm bảo giá trị tiếp theo là 42 (trong trường hợp này).

0

Có vẻ vô lý là bạn không thể đặt/đặt lại cột nhận dạng bằng một lệnh duy nhất để bao gồm cả hai trường hợp bảng có chèn hồ sơ hay không. Tôi không thể hiểu được hành vi mà tôi đã trải qua cho đến khi tôi vấp phải câu hỏi trên trên SO! Giải pháp của tôi - xấu xí nhưng hoạt động - là kiểm tra rõ ràng bảng sys.identity_columns.last_value cho bạn biết bảng đã có bản ghi đã chèn hay chưa và gọi lệnh DBCC CHECKIDENT thích hợp trong mỗi trường hợp: DECLARE @last_value INT = CONVERT(INT, (SELECT last_value FROM sys.identity_columns WHERE OBJECT_NAME(OBJECT_ID) = 'MyTable')); IF @last_value IS NULL BEGIN -- Table newly created and no rows inserted yet; start the IDs off from 1 DBCC CHECKIDENT ('MyTable', RESEED, 1); END ELSE BEGIN -- Table has rows; ensure the IDs continue from the last ID used DECLARE @lastValUsed INT = (SELECT ISNULL(MAX(ID),0) FROM MyTable); DBCC CHECKIDENT ('MyTable', RESEED, @lastValUsed); END

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