Silme işleminden sonra SQL Server'da Otomatik Geliştirme'yi sıfırlama


265

SQL Server veritabanındaki bir tablodan bazı kayıtları sildim. Şimdi kimlik 101'den 1200'e gider. Kayıtları tekrar silmek istiyorum, ancak kimliklerin 102'ye geri dönmesini istiyorum. SQL Server'da bunu yapmanın bir yolu var mı?


46
Lütfen "Yapma" demeyin. Bir şeyi nasıl yapacağımı sorduğumda nefret ediyorum ve elde ettiğim tek şey değil. Evet, kimliğin sıfırlanması yabancı anahtar sorunlarına neden olabilir, ancak veritabanınızı ve programınızı buna göre bilmiyorsanız. Belirtilen bir silme işleminden sonra bir kimliği sıfırlamanın çok iyi nedenleri vardır - bunlara Denetçiler denir. Denetçiler boşlukları görmekten nefret ederler, bu yüzden onları doldururlar, kontrollü bir şekilde yaparlar ve yabancı anahtar çelişkilerinin korunmasını sağlarlar.

6
@spyder, bir kayıt eki yalnızca silmek için geri alınmazsa boşluklar olacağını biliyor muydunuz? Bir otomatik entrement ile boşluklardan kaçınamazsınız ve denemek aptalca. Bir denetim kurumu için çalıştım ve yetkili denetçiler bunu açıklayabilir. Ayrıca, uygun denetim tablolarınız varsa, bu kayıtlara ne olduğunu görebilirler. Veya yasal nedenlerden ötürü hiçbir boşluk olmaması gerekiyorsa (bunun birkaç örneği vardır), o zaman sadece beceriksiz bir geliştirici bir otomatik girişim kullanır ve denetçiler haklı olarak üzülür.
HLGEM

Yanıtlar:


454

1'den başlayarak mytable'ı yeniden göndermek için aşağıdaki komutu verin:

DBCC CHECKIDENT (mytable, RESEED, 0)

Bu konuyu on line kitaplarda (BOL, SQL yardımı) okuyun. Ayrıca, ayarladığınız tohumdan daha yüksek kayıtlara sahip olmadığınıza da dikkat edin.


4
... çünkü bu kayıtların kimlikleri mutlu bir şekilde tekrar kullanılacak ve kötü bir karmaşaya neden olacak.
nalply

3
Aslında, kimlikleri 1'de başlatmak için 0 kullanmanız gerekir: DBCC CHECKIDENT (mytable, RESEED, 0)
Ryan Lundy

7
"DBCC CHECKIDENT (table_name)", "dikkatli
olmanıza

4
@ user1027167 Hayır, yanıtınız benim için çalışmadı. Dahili olarak kaydettiği en yüksek kimliği arttırmaya devam etti. Benim durumumda bir sonraki kimlik olarak "19" almak için açıkça "RESEED, 18" kullanmak zorunda kaldı. Olmadan mutlu "29" artmaya devam etti.
Matthis Kohli

DBCC CHECKIDENT (tablo_adı), yalnızca kimlik değeri sütundaki maksimum değerden düşükse tohum değiştirir . Bu nedenle, kimlik değeri @MatthisKohli durumu gibi zaten daha büyükse, açık reseed çağrılmalıdır.
Martheen

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

sayı = 0 ise, sonraki eklemede otomatik artış alanı 1 değerini içerir

sayı = 101 ise, sonraki eklemede otomatik artış alanı 102 değerini içerecektir


Bazı ek bilgiler ... Sizin için faydalı olabilir Yukarıdaki sorguda

otomatik artış vermeden önce number, mevcut tablonuzun otomatik artış sütununda bundan daha az değerler bulunduğundan emin olmalısınız number.

Bir sütundan (sütun_adı) bir tablodan (tablo1) maksimum değeri almak için aşağıdaki sorguyu kullanabilirsiniz

 SELECT MAX(column_name) FROM table1

37

yarı aptal geçirmez:

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 (tablo_adı)" aynı şeyi yapar (yarış koşulları olmadan mümkündür)
user1027167

2
@ user1027167 Dokümanlar 'bir tablonun geçerli kimlik değeri kimlik sütununda depolanan maksimum kimlik değerinden düşükse'; veriler silindikten sonra temizlemeyi kapsamaz (kimlikleri yeniden kullanmak - genellikle kötü bir fikirdir). SQL 2008'de doğrulandı
user423430

1
En iyi sistematik ve otomatik cevap. Bravo!
Mehdi Khademloo


6

Veritabanındaki tüm tabloları silin ve yeniden gönderin.

    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

Bunu anladım. Onun:

 DBCC CHECKIDENT ('tablename', RESEED, newseed)

4

Şema kalifikasyonu ile benzer bir sorunla karşılaşanlar için kabul edilen cevaba dayanarak:

( [MyDataBase].[MySchemaName].[MyTable]) ... bir hatayla sonuçlanırsa, o DB bağlamında olmanız gerekir

Yani, aşağıdakiler bir hata verecektir:

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

Tam olarak nitelenmiş tablo adını tek tırnak işareti içine alın:

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

4

Birkaç cevap böyle bir ifadeyi kullanmanızı önerir:

DBCC CHECKIDENT (mytable, RESEED, 0)

Ancak OP, hepsi olmayabilir "bazı kayıtları sildi" dedi, bu nedenle 0 değeri her zaman doğru değildir. Başka bir cevap, maksimum akım değerini otomatik olarak bulmayı ve bu değere yeniden göndermeyi önerdi, ancak tabloda hiç kayıt yoksa sorun çıkar ve max () NULL döndürür. Basitçe önerilen bir yorum

DBCC CHECKIDENT (mytable)

değeri sıfırlamak için, ancak başka bir yorum, bunun yalnızca değeri zaten tablodaki maksimum değere yükselttiğini doğru bir şekilde belirtti; bu zaten tabloda maksimumdan daha yüksekse, OP'nin yapmak istediği değeri azaltmaz.

Daha iyi bir çözüm bu fikirleri birleştirir. İlk CHECKIDENT değeri 0 olarak, ikincisi de tabloda kayıt olması durumunda değeri tablodaki en yüksek değere sıfırlar:

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

Birden fazla yorumun belirttiği gibi, diğer tablolarda silinen kayıtları gösteren yabancı anahtar olmadığından emin olun. Aksi takdirde, bu yabancı anahtarlar, tabloyu yeniden boyutlandırdıktan sonra oluşturduğunuz kayıtlara işaret edecektir;


4

DBCC CHECKIDENTTablolar için şemalar kullandığınızda -approach ürün sorunları olacaktır çünkü bu yanıtı eklemek istiyorum . Emin olmak için bunu kullanın:

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

Operasyonun başarısını kontrol etmek istiyorsanız,

SELECT IDENT_CURRENT(@Table);

0yukarıdaki örnekte çıktı alınmalıdır .


1

Bunu genel olarak yapmak istemezsiniz. Reseed veri bütünlüğü sorunları yaratabilir. Gerçekten sadece tüm test verilerini sildiğiniz ve baştan başladığınız geliştirme sistemlerinde kullanım içindir. İlgili tüm kayıtların silinmemesi durumunda üretim sisteminde kullanılmamalıdır (yabancı anahtar ilişkisinde olması gereken her tablo değildir!). Bunu yaparken bir karmaşa yaratabilirsiniz ve özellikle her silme işleminden sonra düzenli olarak yapmak istiyorsanız. Kimlik alanı değerlerinizdeki boşluklar konusunda endişe etmek kötü bir fikirdir.


6
Ben her zaman kullanmayacağım ve sadece bir test db oldu.
jumbojs

0

Peki buna ne dersin?

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

Bu, otomatik artışı 0'a veya istediğiniz herhangi bir sayıya değiştirmenin hızlı ve basit bir yoludur. Ben bir veritabanı ihraç ve kodu kendim okuyarak bunu anladım.

Tek satırlık bir çözüm yapmak için şöyle de yazabilirsiniz:

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

1
Sınırlı ve anında yardım sağlayabilecek bu kod snippet'i için teşekkür ederiz. Bir Doğru bir açıklama ölçüde uzun vadeli değer artıracak göstererek neden bu soruna iyi bir çözüm olduğunu ve diğer benzer sorularla gelecek okuyucularına daha kullanışlı bir hale getirecektir. Yaptığınız varsayımlar dahil bazı açıklamalar eklemek için lütfen yanıtınızı düzenleyin .
Elveda StackExchange
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.