2009-02-04 29 views
199

Tôi đã xóa một số bản ghi từ một bảng trong cơ sở dữ liệu SQL Server. Bây giờ ID của đi từ 101 đến 1200. Tôi muốn xóa các hồ sơ một lần nữa, nhưng tôi muốn ID của để quay trở lại 102. Có cách nào để làm điều này trong SQL Server?Đặt lại AutoIncrement trong SQL Server sau khi xóa

+33

Vui lòng không nói "Không làm điều đó". Tôi ghét nó khi tôi hỏi làm thế nào để làm một cái gì đó và tất cả tôi nhận được là không. Việc đặt lại danh tính có thể gây ra các vấn đề về khóa ngoại nhưng chỉ khi bạn không biết cơ sở dữ liệu và chương trình của bạn tương ứng. Có những lý do rất tốt để đặt lại danh tính sau khi xóa được xóa - chúng được gọi là Người kiểm tra. Kiểm toán viên ghét để xem những khoảng trống để điền vào chúng, làm điều đó một cách có kiểm soát và đảm bảo các ràng buộc khóa ngoại được duy trì. –

+6

@spyder, bạn có biết rằng bạn sẽ có khoảng trống nếu chèn bản ghi được cuộn lại không chỉ để xóa? Bạn không thể tránh những khoảng trống với một autoincrement và nó là ngu ngốc để thử. Tôi đã làm việc cho một cơ quan kiểm toán và kiểm toán viên có thẩm quyền có thể giải thích cho họ. Hơn nữa nếu bạn có bảng kiểm toán thích hợp, họ có thể xem những gì đã xảy ra với những hồ sơ đó. Hoặc nếu không có khoảng trống bao giờ vì lý do pháp lý (có một vài trường hợp này), thì chỉ có một nhà phát triển không đủ năng lực sẽ sử dụng một autoincrement và kiểm toán viên là đúng khó chịu. – HLGEM

Trả lời

348

Issue lệnh sau để gieo hạt mytable để bắt đầu lúc 1:

DBCC CHECKIDENT (mytable, RESEED, 0) 

đọc về nó trong Sách trên Line (BOL, SQL giúp đỡ). Cũng hãy cẩn thận rằng bạn không có hồ sơ cao hơn hạt giống bạn đang thiết lập.

+3

... vì các id của các hồ sơ này sẽ được vui vẻ tái sử dụng một lần nữa, gây ra một mớ hỗn độn xấu. – nalply

+0

làm thế nào về một số không? – Joset

+3

Trên thực tế, để bắt đầu ID tại 1, bạn cần sử dụng 0: 'DBCC CHECKIDENT (mytable, RESEED, 0)' –

3

Tôi đã tìm ra. Đó là:

DBCC CHECKIDENT ('tablename', RESEED, newseed) 
2

Bạn không muốn thực hiện việc này nói chung. Reseed có thể tạo ra các vấn đề toàn vẹn dữ liệu. Nó thực sự chỉ để sử dụng trên các hệ thống phát triển nơi bạn đang xóa sạch tất cả dữ liệu thử nghiệm và bắt đầu lại. Nó không nên được sử dụng trên một hệ thống sản xuất trong trường hợp tất cả các hồ sơ liên quan đã không bị xóa (không phải tất cả các bảng phải ở trong một mối quan hệ khóa ngoại là!). Bạn có thể tạo ra một mess làm điều này và đặc biệt là nếu bạn có nghĩa là để làm điều đó một cách thường xuyên sau mỗi xóa. Đó là một ý tưởng tồi để lo lắng về những khoảng trống trong các giá trị trường nhận dạng của bạn.

+6

Tôi sẽ không sử dụng nó mọi lúc và nó chỉ trên một db thử nghiệm. – jumbojs

29

bán idiot-proof:

declare @max int; 
select @max = max(key) from table; 
dbcc checkident(table,reseed,@max) 

http://sqlserverplanet.com/tsql/using-dbcc-checkident-to-reseed-a-table-after-delete

+1

"DBCC CHECKIDENT (tên_bảng)" không giống nhau (có thể không có điều kiện chủng tộc) – user1027167

+2

@ user1027167 Tài liệu nói 'nếu giá trị danh tính hiện tại cho một bảng nhỏ hơn giá trị nhận dạng tối đa được lưu trữ trong cột nhận dạng'; mà không bao gồm dọn dẹp sau khi dữ liệu bị xóa (tái sử dụng id - thường là một ý tưởng tồi). Đã được xác minh trên SQL 2008 – user423430

+1

Câu trả lời có hệ thống và tự động tốt nhất. Bravo! –

63
DBCC CHECKIDENT('databasename.dbo.tablename', RESEED, number) 

nếu number = 0 sau đó trong chèn tiếp theo lĩnh vực tự động tăng sẽ chứa giá trị 1

nếu number = 101 sau đó trong trường chèn tiếp theo, trường tăng tự động sẽ chứa giá trị 102


Một số thông tin bổ sung ... Có thể hữu ích cho bạn

Trước khi đưa ra tự động tăng number trong truy vấn trên, bạn phải chắc chắn cột tự động tăng bảng hiện có của bạn chứa các giá trị ít mà number.

Để có được giá trị lớn nhất của một cột (column_name) từ một bảng (table1), bạn có thể sử dụng sau đây truy vấn

SELECT MAX(column_name) FROM table1 
7

Hãy thử điều này:

ALTER TABLE tablename AUTO_INCREMENT = 1 
+4

Nếu tôi không sai, câu trả lời là tốt cho mysql mặc dù. – Carol

+1

Đây là câu trả lời cho MySQL. OP đang hỏi về MSSQL. – reformed

5

Xóa và gieo hạt tất cả các bảng trong cơ sở dữ liệu.

USE [DatabaseName] 
    EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"  -- Disable All the constraints 
    EXEC sp_MSForEachTable "DELETE FROM ?" -- Delete All the Table data 
    Exec sp_MSforeachtable 'DBCC CHECKIDENT(''?'', RESEED, 0)' -- Reseed All the table to 0 
    Exec sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all" -- Enable All the constraints back 

-- You may ignore the errors that shows the table without Auto increment field. 
4

Dựa trên câu trả lời được chấp nhận, đối với những người gặp phải một vấn đề tương tự, có trình độ sơ đồ đầy đủ:

([MyDataBase].[MySchemaName].[MyTable]) ...kết quả trong một lỗi, bạn cần phải trong bối cảnh mà DB

Đó là, sau đây sẽ ném ra một lỗi:

DBCC CHECKIDENT ([MyDataBase].[MySchemaName].[MyTable], RESEED, 0) 

Kèm theo tên bảng đầy đủ điều kiện với dấu nháy đơn thay vì:

DBCC CHECKIDENT ('[MyDataBase].[MySchemaName].[MyTable]', RESEED, 0) 
2

một số câu trả lời khuyên bạn sử dụng một cái gì đó tuyên bố như thế này:

DBCC CHECKIDENT (mytable, RESEED, 0) 

Nhưng OP cho biết "xóa một số bản ghi", có thể không phải tất cả chúng, vì vậy giá trị 0 không phải lúc nào cũng đúng. Một câu trả lời khác gợi ý tự động tìm giá trị hiện tại tối đa và chèn lại vào giá trị hiện tại, nhưng điều đó sẽ gặp rắc rối nếu không có bản ghi nào trong bảng, và do đó max() sẽ trả về NULL. Nhận xét được đề xuất chỉ sử dụng đơn giản là

DBCC CHECKIDENT (mytable) 

để đặt lại giá trị, nhưng một nhận xét khác cho biết chính xác điều này chỉ làm tăng giá trị cho giá trị tối đa đã có trong bảng; điều này sẽ không làm giảm giá trị nếu nó đã cao hơn giá trị tối đa trong bảng, đó là những gì OP muốn làm.

Một giải pháp tốt hơn kết hợp các ý tưởng này. Các CHECKIDENT đầu tiên reset giá trị 0, và resets thứ hai nó với giá trị cao nhất hiện nay trong bảng, trong trường hợp có các bản ghi trong bảng:

DBCC CHECKIDENT (mytable, RESEED, 0) 
DBCC CHECKIDENT (mytable) 

Như nhiều ý kiến ​​đã chỉ ra, hãy chắc chắn không có các khóa ngoại trong các bảng khác trỏ đến các bản ghi đã xóa. Nếu không, các khóa ngoại sẽ trỏ vào các bản ghi bạn tạo sau khi chèn lại bảng, gần như chắc chắn không phải là những gì bạn có trong tâm trí.

0

Tôi muốn thêm câu trả lời này vì DBCC CHECKIDENT -ứng dụng sẽ xảy ra sự cố sản phẩm khi bạn sử dụng lược đồ cho bảng. Sử dụng điều này để chắc chắn:

DECLARE @Table AS NVARCHAR(500) = 'myschema.mytable'; 
DBCC CHECKIDENT (@Table, RESEED, 0); 

Nếu bạn muốn kiểm tra sự thành công của các hoạt động, sử dụng

SELECT IDENT_CURRENT(@Table); 

mà nên đầu ra 0 trong ví dụ trên.

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