Đặt lại AutoIncrement trong SQL Server sau khi xóa


266

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 đi từ 101 đến 1200. Tôi muốn xóa các bản ghi một lần nữa, nhưng tôi muốn ID trở lại 102. Có cách nào để làm điều này trong SQL Server không?


46
Xin đừng nói "Đừng làm thế". 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ả những gì tôi nhận được là không. Có, việc đặt lại danh tính có thể gây ra sự cố khóa ngoài nhưng chỉ khi bạn không biết cơ sở dữ liệu và chương trình phù hợp. Có những lý do rất chính đáng để đặt lại danh tính sau khi xóa bỏ - chúng được gọi là Kiểm toán viên. Kiểm toán viên ghét nhìn thấy những khoảng trống để lấp đầy chúng, thực hiện nó một cách có kiểm soát và đảm bảo các hạn chế khóa ngoại được duy trì.

6
@spyder, bạn có biết rằng bạn sẽ có những khoảng trống nếu một bản ghi chèn được khôi phục không chỉ để xóa? Bạn không thể tránh những khoảng trống với sự tự động và thật ngu ngốc khi 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 điều này cho họ. Hơn nữa nếu bạn có các bảng kiểm toán thích hợp, họ có thể thấy 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 như vậy), thì chỉ có một nhà phát triển không đủ năng lực sẽ sử dụng tự động và các kiểm toán viên rất khó chịu.
HLGEM

Câu trả lời:


455

Ban hành lệnh sau để khởi động lại mytable để bắt đầu lúc 1:

DBCC CHECKIDENT (mytable, RESEED, 0)

Đọc về nó trong Sách trực tuyến (BOL, trợ giúp SQL). Ngoài ra, 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.


4
... bởi vì id của những hồ sơ này sẽ vui vẻ được sử dụng lại, gây ra một mớ hỗn độn tồi tệ.
nalply

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

7
"DBCC CHECKIDENT (tên_bảng)" đặt hạt giống thành danh tính cao nhất trong bảng, hơn là bạn không phải "cẩn thận"
user1027167

4
@ user1027167 Không, câu trả lời của bạn không phù hợp với tôi. Nó tiếp tục tăng trên ID cao nhất mà nó đã lưu trong nội bộ. Tôi đã phải sử dụng rõ ràng "RESEED, 18" trong trường hợp của mình để lấy "19" làm ID tiếp theo. Không có nó tiếp tục vui vẻ tăng lên vào "29".
Matthis Kohli

DBCC CHECKIDENT (tên_bảng) chỉ thay đổi hạt giống nếu giá trị nhận dạng thấp hơn giá trị tối đa trong cột. Vì vậy, nếu giá trị danh tính đã lớn hơn như trường hợp @MatthisKohli, thì phải gọi lại rõ ràng.
Martheen

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

if number = 0 thì trong lần chèn tiếp theo, trường tăng tự động sẽ chứa giá trị 1

nếu số = 101 thì trong lần 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 mức tăng tự động numbertrong truy vấn trên, bạn phải đảm bảo cột tăng tự động của bảng hiện có chứa các giá trị ít hơn number.

Để lấy giá trị tối đa của một cột (cột_name) từ một bảng (bảng1), bạn có thể sử dụng truy vấn sau

 SELECT MAX(column_name) FROM table1

37

bán ngớ ngẩn:

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

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


1
"DBCC CHECKIDENT (tên_bảng)" cũng làm như vậy (có thể không có điều kiện chủng tộc)
user1027167

2
@ user1027167 Các tài liệu nói 'nếu giá trị nhận dạng 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 danh'; không bao gồm dọn dẹp sau khi dữ liệu bị xóa (sử dụng lại id - thường là một ý tưởng tồi). Đã xác minh trên SQL 2008
user423430

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

11

Nếu bạn đang sử dụng MySQL, hãy thử điều này:

ALTER TABLE tablename AUTO_INCREMENT = 1

3
Đây là một câu trả lời cho MySQL. OP đang hỏi về MSSQL.
cải cách

câu hỏi là về MS SQL Server
Saher Ahwal

6

Xóa và lấy lại 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.

6

Tôi đã hiểu rồi. Nó là:

 DBCC CHECKIDENT ('tablename', RESEED, newseed)

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 vấn đề tương tự, với trình độ lược đồ đầy đủ:

( [MyDataBase].[MySchemaName].[MyTable]) ... dẫn đến một lỗi, bạn cần phải ở trong bối cảnh của DB đó

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

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

Thay vào đó, hãy đặt tên bảng đủ điều kiện bằng dấu ngoặc đơn:

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

4

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

DBCC CHECKIDENT (mytable, RESEED, 0)

Nhưng OP cho biết "đã xóa một số hồ sơ", có thể không phải là tất cả trong số họ, 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 đề nghị tự động tìm giá trị hiện tại tối đa và khởi động lại giá trị đó, nhưng nó sẽ gặp rắc rối nếu không có bản ghi trong bảng và do đó max () sẽ trả về NULL. Một bình luận được đề xuất sử dụng đơn giản

DBCC CHECKIDENT (mytable)

để đặt lại giá trị, nhưng một nhận xét khác đã nêu chính xác rằng điều này chỉ làm tăng giá trị lên mức 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 mức tối đa trong bảng, đó là điều mà OP muốn làm.

Một giải pháp tốt hơn kết hợp những ý tưởng này. CHECKIDENT đầu tiên đặt lại giá trị thành 0 và lần thứ hai đặt lại giá trị cao nhất hiện tại 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 bình luận đã chỉ ra, hãy đảm bảo không có khóa ngoại trong các bảng khác trỏ đến các bản ghi bị xóa. Nếu không, các khóa ngoại đó sẽ trỏ đến các bản ghi bạn tạo sau khi sắp xếp lại bảng, điều này gần như chắc chắn không phải là những gì bạn có trong tâm trí.


4

Tôi muốn thêm câu trả lời này vì DBCC CHECKIDENT-approach sẽ tạo ra vấn đề khi bạn sử dụng lược đồ cho các 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 hoạt động, hãy sử dụng

SELECT IDENT_CURRENT(@Table);

mà nên xuất ra 0trong ví dụ trên.


1

Bạn không muốn làm điều này nói chung. Reseed có thể tạo ra vấn đề toàn vẹn dữ liệu. Nó thực sự chỉ được 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. Không nên sử dụng nó trên một hệ thống sản xuất trong trường hợp tất cả các bản ghi liên quan chưa bị xóa (không phải tất cả các bảng trong mối quan hệ khóa ngoài là!). Bạn có thể tạo ra một mớ hỗn độn làm điều này và đặc biệt nếu bạn muốn làm điều đó một cách thường xuyên sau mỗi lần 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ỉ có trên một db thử nghiệm.
jumbojs

0

Cái này thì sao?

ALTER TABLE `table_name`
  MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

Đây là một cách nhanh chóng và đơn giản để thay đổi mức tăng tự động thành 0 hoặc bất kỳ số nào bạn muốn. Tôi đã tìm ra điều này bằng cách xuất một cơ sở dữ liệu và tự đọc mã.

Bạn cũng có thể viết nó như thế này để biến nó thành một giải pháp một dòng:

ALTER TABLE `table_name` MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

1
Cảm ơn bạn vì đoạn mã này, có thể cung cấp một số trợ giúp hạn chế, ngay lập tức. Một lời giải thích phù hợp sẽ cải thiện đáng kể giá trị lâu dài của nó bằng cách chỉ ra lý do tại sao đây là một giải pháp tốt cho vấn đề và sẽ giúp nó hữu ích hơn cho những người đọc tương lai với những câu hỏi tương tự khác. Vui lòng chỉnh sửa câu trả lời của bạn để thêm một số giải thích, bao gồm các giả định bạn đã thực hiện.
Tạm biệt StackExchange
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.