รีเซ็ตเมล็ดข้อมูลเฉพาะตัวหลังจากลบระเบียนใน SQL Server


682

ฉันได้แทรกบันทึกลงในตารางฐานข้อมูล SQL Server ตารางมีคีย์หลักที่กำหนดไว้และเมล็ดข้อมูลเฉพาะตัวของการเพิ่มอัตโนมัติถูกตั้งค่าเป็น "ใช่" สิ่งนี้เกิดขึ้นได้เนื่องจากใน SQL Azure แต่ละตารางจะต้องมีคีย์หลักและข้อมูลระบุตัวตน

แต่เนื่องจากฉันต้องลบบางระเบียนจากตารางเมล็ดข้อมูลประจำตัวสำหรับตารางเหล่านั้นจะถูกรบกวนและคอลัมน์ดัชนี (ซึ่งสร้างขึ้นโดยอัตโนมัติโดยเพิ่มขึ้น 1) จะถูกรบกวน

ฉันจะรีเซ็ตคอลัมน์ข้อมูลประจำตัวหลังจากที่ฉันลบระเบียนเพื่อให้คอลัมน์มีลำดับในการเรียงลำดับตัวเลขจากน้อยไปมาก

คอลัมน์ข้อมูลประจำตัวไม่ได้ใช้เป็น foreign key ในฐานข้อมูล


4
"ใน SQL Azure" - "แต่ละตารางจะต้องมีคีย์หลัก" - true - "และ Identity Defined" - false รหัสประจำตัวและคีย์หลักคือแนวคิดมุมฉาก คอลัมน์ข้อมูลประจำตัวไม่จำเป็นต้องเป็น PK ของตาราง คีย์หลักไม่จำเป็นต้องเป็นคอลัมน์ข้อมูลประจำตัว
Damien_The_Unbeliever

ตกลง. แนวคิดของฉันอาจผิด แต่ตอนนี้ฉันได้กำหนดโครงสร้างของตารางด้วย PK และ Identity Seed แล้ว หากฉันต้องลบบางแถวฉันจะรีเซ็ต Identity Seed ในลำดับตัวเลขที่ถูกต้องได้
อย่างไร

29
ฉันมักจะยืนยันว่าหากคุณสนใจค่าตัวเลขจริงที่สร้างขึ้นในคอลัมน์ข้อมูลประจำตัวคุณจะใช้ผิดวัตถุประสงค์ สิ่งที่คุณควรใส่ใจเกี่ยวกับคอลัมน์ข้อมูลประจำตัวคือมันจะสร้างค่าที่ไม่ซ้ำกันโดยอัตโนมัติ (yay!) และคุณสามารถเก็บค่าเหล่านี้ไว้ในคอลัมน์ตัวเลขได้ (บิตนี้เกี่ยวข้องกับการประกาศคอลัมน์เพื่อเก็บค่าเหล่านี้เท่านั้น) คุณไม่ควรแสดงให้คนอื่นเห็นดังนั้นจึงไม่ควรให้คุณค่ากับสิ่งที่พวกเขาทำ
Damien_The_Unbeliever

คุณสามารถใช้การระบุตัวตรวจสอบ dbcc ตามที่กล่าวไว้อื่น ๆ แต่โปรดทราบว่าคีย์หลักไม่บังคับสำหรับ sql db v12
Satya_MSFT

คำตอบ:


1099

DBCC CHECKIDENTคำสั่งการจัดการจะใช้ในการตั้งค่าตัวตนที่เคาน์เตอร์ ไวยากรณ์คำสั่งคือ:

DBCC CHECKIDENT (table_name [, { NORESEED | { RESEED [, new_reseed_value ]}}])
[ WITH NO_INFOMSGS ]

ตัวอย่าง:

DBCC CHECKIDENT ('[TestTable]', RESEED, 0);
GO

ไม่รองรับในฐานข้อมูล Azure SQL เวอร์ชันก่อนหน้า แต่ได้รับการสนับสนุนแล้ว


โปรดทราบว่าnew_reseed_valueข้อโต้แย้งนั้นเปลี่ยนแปลงไปตามรุ่นของ SQL Server ตามเอกสารประกอบ :

หากมีแถวในตารางแถวถัดไปจะถูกแทรกด้วยค่าnew_reseed_value ในเวอร์ชัน SQL Server 2008 R2 และก่อนหน้าแถวถัดไปที่แทรกจะใช้new_reseed_value + ค่าส่วนเพิ่มปัจจุบัน

อย่างไรก็ตามฉันพบว่าข้อมูลนี้ทำให้เข้าใจผิด (ผิดธรรมดาจริง ๆ เท่านั้น) เนื่องจากพฤติกรรมที่สังเกตเห็นบ่งชี้ว่าอย่างน้อย SQL Server 2012 ยังคงใช้new_reseed_value + ตรรกะมูลค่าเพิ่มปัจจุบัน Microsoft ยังขัดแย้งกับที่Example Cพบในหน้าเดียวกัน:

C. การบังคับให้ค่าตัวตนปัจจุบันเป็นค่าใหม่

ตัวอย่างต่อไปนี้บังคับให้ค่าตัวตนปัจจุบันในคอลัมน์ AddressTypeID ในตาราง AddressType เป็นค่า 10 เนื่องจากตารางมีแถวที่มีอยู่แถวถัดไปที่แทรกจะใช้ 11 เป็นค่านั่นคือค่าเพิ่มใหม่ปัจจุบันที่กำหนดไว้สำหรับ ค่าคอลัมน์บวก 1

USE AdventureWorks2012;  
GO  
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);  
GO

แต่ถึงกระนั้นทั้งหมดนี้ยังมีตัวเลือกสำหรับลักษณะการทำงานที่แตกต่างกันใน SQL Server เวอร์ชันที่ใหม่กว่า ฉันเดาวิธีเดียวที่จะมั่นใจได้ว่าจนกว่า Microsoft จะล้างสิ่งต่าง ๆ ในเอกสารของตัวเองคือทำการทดสอบจริงก่อนการใช้งาน


23
ไวยากรณ์จะเป็น ... DBCC CHECKIDENT ('[TestTable]', RESEED, 0) GO
Biki

2
ดูเหมือนว่าDBCC CHECKIDENTได้รับการสนับสนุนในฐานะของการเปิดตัวที่จะเกิดขึ้น (V12 / สเตอร์ลิง): azure.microsoft.com/en-us/documentation/articles/ ......แม้ว่าสำหรับสถานการณ์เฉพาะนี้ฉันยังคงแนะนำตาราง TRUNCATE :)
โซโลมอน Rutzky

1
มันไม่ได้ผลสำหรับฉันจนกว่า "GO" จะอยู่ในอีกบรรทัดหนึ่ง
mrówa

1
ไวยากรณ์ได้รับการกำหนดธงเนื่องจากคำหลัก GO ในบรรทัดเดียวกันฉันไม่ทราบสาเหตุ คุณช่วยเลื่อนมันลงมาได้ไหม ฉันคัดลอกและวางบรรทัดนี้ 50 ครั้งและตอนนี้ฉันต้องย้อนกลับและแก้ไข
AnotherDeveloper

4
ทำงานอย่างสมบูรณ์แบบสำหรับฉัน มันคุ้มค่าที่ชี้ให้เห็นว่าเมื่อมีการเพาะตารางถ้าคุณต้องการที่จะ reseed เพื่อให้บันทึกแรกของคุณคือหมายเลข 1 แล้วคำสั่ง RESEED ต้อง reseed 0 เพื่อให้บันทึกต่อไปคือหมายเลข 1
ไมค์อัพจอห์

215
DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO

โดยที่ 0 คือidentityค่าเริ่มต้น


15
หากตารางว่างเปล่าเช่นถ้าคุณเพิ่งเรียกTRUNCATEใช้ค่าเมล็ดใหม่ควรเป็นค่าสำหรับการใช้งานครั้งถัดไป (เช่น 1 ไม่ใช่ 0) new_reseed_value + 1ถ้าตารางไม่ว่างก็จะใช้ MSDN
kjbartel

2
@kjbartel, Anil และคนอื่น ๆ : มันไม่ง่ายเหมือน "ถ้าตารางว่างเปล่า" เอกสารที่ขาดหายไปสำหรับกรณีเมื่อตารางเป็นที่ว่างเปล่าเนื่องจากDELETEไม่ซึ่งในกรณีนี้ก็ยังเป็นTRUNCATE new_reseed+value + 1ฉันเขียนบทความเกี่ยวกับเรื่องนี้แสดงพฤติกรรมที่แท้จริงผ่านการทดสอบบางอย่างและอัปเดตเอกสารจริง (ตอนนี้เราสามารถทำได้เนื่องจากอยู่ใน GitHub): การตรวจสอบ DBCC ทำงานอย่างไรจริง ๆ เมื่อรีเซ็ตเมล็ดข้อมูลประจำตัว (RESEED) .
โซโลมอน Rutzky

87

ควรสังเกตว่าหากข้อมูลทั้งหมดจะถูกลบออกจากตารางผ่านทางDELETE(เช่นไม่มีWHEREส่วนคำสั่ง) จากนั้นตราบเท่าที่ a) สิทธิ์อนุญาตสำหรับมันและ b) ไม่มี FK ที่อ้างถึงตาราง (ซึ่งดูเหมือนจะเป็น กรณีที่นี่) การใช้TRUNCATE TABLEจะเป็นที่ต้องการเพราะมันมีประสิทธิภาพมากขึ้นDELETE และรีเซ็ตIDENTITYเมล็ดในเวลาเดียวกัน รายละเอียดต่อไปนี้นำมาจากหน้า MSDN สำหรับTRUNCATE TABLE :

เปรียบเทียบกับคำสั่ง DELETE ตาราง TRUNCATE มีข้อดีดังต่อไปนี้:

  • ใช้พื้นที่บันทึกธุรกรรมน้อย

    คำสั่ง DELETE ลบแถวทีละรายการและบันทึกรายการในบันทึกธุรกรรมสำหรับแต่ละแถวที่ถูกลบ TRUNCATE TABLE ลบข้อมูลโดยการยกเลิกการจัดสรรหน้าข้อมูลที่ใช้ในการจัดเก็บข้อมูลตารางและบันทึกเฉพาะการยกเลิกการจัดสรรหน้าในบันทึกการทำธุรกรรม

  • ล็อคที่น้อยลงมักจะใช้

    เมื่อคำสั่ง DELETE ดำเนินการโดยใช้การล็อคแถวแต่ละแถวในตารางจะถูกล็อคเพื่อลบ TRUNCATE TABLE จะล็อคตาราง (รวมถึงล็อค schema (SCH-M)) และหน้า แต่ไม่แต่ละแถว

  • โดยไม่มีข้อยกเว้นหน้าศูนย์เหลืออยู่ในตาราง

    หลังจากดำเนินการคำสั่ง DELETE ตารางยังสามารถมีหน้าว่างได้ ตัวอย่างเช่นหน้าว่างในฮีปไม่สามารถยกเลิกการจัดสรรคืนได้หากไม่มีล็อคตารางแบบพิเศษ (LCK_M_X) เป็นพิเศษ หากการลบไม่ได้ใช้การล็อคตารางตาราง (ฮีป) จะมีหน้าว่างหลายหน้า สำหรับดัชนีการลบสามารถทิ้งหน้าเปล่าไว้ด้านหลังแม้ว่าหน้าเหล่านี้จะถูกจัดสรรคืนอย่างรวดเร็วโดยกระบวนการล้างพื้นหลัง

หากตารางมีคอลัมน์ข้อมูลเฉพาะตัวตัวนับสำหรับคอลัมน์นั้นจะถูกรีเซ็ตเป็นค่าเมล็ดที่กำหนดไว้สำหรับคอลัมน์ หากไม่มีการกำหนดเมล็ดพันธุ์จะใช้ค่าเริ่มต้น 1 หากต้องการเก็บตัวนับข้อมูลประจำตัวให้ใช้ DELETE แทน

ดังนั้นต่อไปนี้:

DELETE FROM [MyTable];
DBCC CHECKIDENT ('[MyTable]', RESEED, 0);

กลายเป็นเพียงแค่:

TRUNCATE TABLE [MyTable];

โปรดดูTRUNCATE TABLEเอกสารประกอบ (ลิงค์ด้านบน) สำหรับข้อมูลเพิ่มเติมเกี่ยวกับข้อ จำกัด ฯลฯ


8
ในขณะที่มีประสิทธิภาพมากขึ้นภายใต้สถานการณ์ที่ถูกต้องนี่ไม่ใช่ตัวเลือกเสมอไป การตัดจะไม่ดำเนินการบนตารางที่มี FK ที่กำหนดไว้ แม้ว่าจะไม่มีเร็กคอร์ดที่ต้องพึ่งพาการตัดทอนจะล้มเหลวหากมีข้อ จำกัด การตัดทอนต้องได้รับอนุญาตจาก ALTER ที่ Delete เพียงต้องการลบ
Rozwel

3
@Rozwel จริง แต่ฉันมีคุณสมบัติคำตอบของฉันแล้วระบุว่าสิทธิ์ที่เหมาะสมจะต้องอยู่ในสถานที่ นอกจากนี้คำถามดังกล่าวระบุว่าไม่มี FKs อย่างไรก็ตามเพื่อความชัดเจนฉันได้ปรับปรุงเพื่อระบุข้อ จำกัด "no FK" ขอบคุณสำหรับการชี้ให้เห็นว่า
โซโลมอน Rutzky

1
เล่นลิ้นเพียงอย่างเดียวคือ FK ใด ๆ จะบล็อกการตัดทอน เป็นไปได้ (แม้ว่าจะผิดปกติ) ที่จะมี FK กับข้อ จำกัด เฉพาะที่ไม่ได้เป็นส่วนหนึ่งของ PK หรือคอลัมน์ข้อมูลประจำตัว
Rozwel

1
@Rozwel เป็นจริงอีกครั้ง แต่ดูเหมือนว่ามีเหตุผลที่จะสมมติจากคำถามที่ว่าไม่มีข้อ จำกัด ที่ไม่ซ้ำกันเนื่องจาก PK มีอยู่เพียงเพราะความเข้าใจของ OP (ถูกต้องหรือไม่) ว่าเป็นที่ต้องการโดย Azure SQL Database ไม่ว่าฉันทุกคนจะลดความกำกวมดังนั้นฉันจึงอัปเดตอีกครั้ง ขอบคุณ
โซโลมอน Rutzky

ไม่ใช่สิ่งที่ผิดปกติที่จะมี foreign key บนโต๊ะและการปรากฏตัวของ foreign key ใด ๆ นั้นห้ามการตัด TRUNCATE Table ฉันเพิ่งค้นพบวิธีนี้ยากก่อนหน้านี้วันนี้เมื่อฉันพยายามเรียกใช้ TRUNCATE TABLE บนตารางที่มีคีย์ต่างประเทศที่บังคับใช้กับคอลัมน์อื่นสองคอลัมน์ในตารางและดัชนีเฉพาะในตารางต่างประเทศ
David A. Gray

83

แม้ว่าคำตอบส่วนใหญ่จะแนะนำให้ RESEED เป็น 0 แต่หลายครั้งเราจำเป็นต้องส่งรหัสประจำตัวถัดไปให้พร้อม

declare @max int
select @max=max([Id])from [TestTable]
if @max IS NULL   //check when max is returned as null
  SET @max = 0
DBCC CHECKIDENT ('[TestTable]', RESEED,@max)

นี่จะตรวจสอบตารางและรีเซ็ตเป็น ID ถัดไป


2
นี่เป็นคำตอบเดียวที่ใช้งานได้ 100%
วิศวกรที่กลับรายการแล้ว

3
สั้นกว่าเล็กน้อย:declare @max int select @max=ISNULL(max([Id]),0) from [TestTable]; DBCC CHECKIDENT ('[TestTable]', RESEED, @max );
Guillermo Prandi

61

ฉันลอง@anil shahsตอบแล้วมันรีเซ็ตตัวตน identity = 2แต่เมื่อแถวใหม่ถูกแทรกมันได้ ดังนั้นฉันเปลี่ยนไวยากรณ์เป็น:

DELETE FROM [TestTable]

DBCC CHECKIDENT ('[TestTable]', RESEED, 0)
GO

จากนั้นแถวแรกจะได้รับ identity = 1



16

ถึงแม้ว่าคำตอบส่วนใหญ่จะบอกRESEEDไป0และในขณะที่บางคนเห็นว่านี่เป็นข้อบกพร่องสำหรับTRUNCATEDตารางไมโครซอฟท์มีทางออกที่ไม่คิดID

DBCC CHECKIDENT ('[TestTable]', RESEED)

IDนี้จะตรวจสอบตารางและการตั้งค่าต่อไป สิ่งนี้มีให้ตั้งแต่ MS SQL 2005 จนถึงปัจจุบัน

https://msdn.microsoft.com/en-us/library/ms176057.aspx


1
น่าเสียดายที่ไม่เป็นความจริง เพิ่งตรวจสอบว่าสำหรับเซิร์ฟเวอร์ MS SQL 2014
alehro

1
จริงๆแล้วมันเป็นเรื่องจริงสำหรับ SQL 2014 ฉันเพิ่งทดสอบและใช้งานได้สำหรับฉัน
Daniel Dyson

2
สิ่งนี้ทำงานได้ไม่สอดคล้องกับฉันใน SQL 2012 บางครั้งมันใช้ตัวที่มีอยู่ถัดไปตามที่ฉันคาดไว้บางครั้งดูเหมือนว่าจะติดอยู่กับค่าเก่าจากตาราง การระบุเมล็ดทำงานได้ดี
Dan Field

ใช้งานไม่ได้กับฉันใน SQL 2016 แต่จะทิ้งเมล็ดข้อมูลประจำตัวตามที่เป็นอยู่ มันอาจจะทำงานได้อย่างถูกต้องสำหรับฉันในครั้งเดียว แต่มันอาจจะเป็นปัญหานิ้วของฉัน ไม่สามารถทำให้มันทำงานได้อีก
วิศวกรที่กลับรายการแล้ว

ข้อความแสดงถึงความสำเร็จChecking identity information: current identity value '[incorrect seed]', current column value '[correct seed]'.แต่เมื่อมีการแทรกใหม่ก็ยังคงใช้เมล็ดพันธุ์ที่ไม่ถูกต้อง
Denziloe

7

การออกคำสั่ง 2 สามารถทำเคล็ดลับ

DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)

การรีเซ็ตเอกลักษณ์ครั้งแรกเป็นศูนย์และถัดไปจะตั้งเป็นค่าที่มีอยู่ถัดไป - jacob


2
DBCC CHECKIDENT ('[TestTable]', RESEED) จะไม่ถูกเปลี่ยนเป็นค่าที่มีอยู่ถัดไป
Atal Kishore

นี่เป็นวิธีการที่ใช้โดยRedGate Data Compareเมื่อเปิดตัวเลือก "Reseed identity identity" ฉันได้ทดสอบมันอย่างกว้างขวาง (ฉันหมายถึงในรหัส SQL ไม่ใช่ในเครื่องมือ RedGate) และทำงานได้อย่างน่าเชื่อถือ (ฉันไม่มีความสัมพันธ์กับ RedGate นอกเหนือจากการเป็นผู้ใช้รุ่นทดลองเป็นครั้งคราว)
วิศวกรที่กลับรายการเมื่อ

6

@jacob

DBCC CHECKIDENT ('[TestTable]', RESEED,0)
DBCC CHECKIDENT ('[TestTable]', RESEED)

ทำงานให้ฉันฉันต้องล้างรายการทั้งหมดก่อนจากตารางจากนั้นเพิ่มข้างต้นในจุดที่เรียกหลังจากลบ ตอนนี้เมื่อใดก็ตามที่ฉันลบรายการถูกนำมาจากที่นั่น


DBCC CHECKIDENT ใช้งานได้หลังจากการลบเท่านั้น คุณอาจใช้การตัดทอน อย่างไรก็ตามหากคุณต้องการข้อมูลส่วนที่เหลืออย่าใช้งาน นอกจากนี้การตัดทอนไม่ได้ให้จำนวนระเบียนของระเบียนที่ถูกลบ
user763539

6

Truncate ตารางเป็นที่ต้องการเพราะมันล้างบันทึกรีเซ็ตตัวนับและเรียกคืนพื้นที่ดิสก์

DeleteและCheckIdentควรใช้เฉพาะกรณีที่กุญแจต่างประเทศป้องกันไม่ให้คุณตัดทอน


5

รีเซ็ตคอลัมน์ข้อมูลประจำตัวด้วยรหัสใหม่ ...

DECLARE @MAX INT
SELECT @MAX=ISNULL(MAX(Id),0) FROM [TestTable]

DBCC CHECKIDENT ('[TestTable]', RESEED,@MAX)

4

นี่เป็นคำถามทั่วไปและคำตอบเหมือนกันเสมอ: อย่าทำ ค่าเอกลักษณ์ควรได้รับการปฏิบัติตามอำเภอใจและดังนั้นจึงไม่มีคำสั่ง "ถูกต้อง"


15
นั่นเป็นเรื่องจริงสำหรับสภาพแวดล้อมการผลิต แต่ในขณะที่การพัฒนาฉันชอบที่จะจำไว้ว่าเอนทิตีบางอย่างมี Id ที่แน่นอนซึ่งบรรจุจากสคริปต์การสร้าง มันทำให้การสำรวจฐานข้อมูลง่ายขึ้นในขณะที่กำลังพัฒนา
Francois Botha

7
คำตอบเช่นนี้เป็นทฤษฎีที่สมบูรณ์และไม่ค่อยสอดคล้องกับความต้องการในโลกแห่งความเป็นจริง วิธีการเกี่ยวกับแทนการล้างสมองคนที่มีความเชื่อของคุณคุณตอบคำถามสหกรณ์ ...
Serj เซแกน

1
ครับเรื่องเย็น. การช่วงชิงของฉันคือ: ถ้าคุณต้องการระบุค่าสำหรับคอลัมน์อย่าเลือกคุณสมบัติในคอลัมน์ที่ทำให้ยาก กลิ่นของรหัสคือ: ถ้าทุกครั้งที่คุณแทรกระเบียนลงในตารางที่คุณระบุค่าสำหรับคอลัมน์ข้อมูลประจำตัวคุณจะไม่มีคอลัมน์ข้อมูลระบุตัวตน จุดรวมของตัวตนคือการให้เซิร์ฟเวอร์สร้างคุณค่าให้กับคุณ ดังนั้นหากคุณแทนที่เวลานั้นคุณจะไม่ได้รับค่าใช้จ่ายที่ไม่เป็นศูนย์ นอกจากนี้ยังใช้งานได้ดีกับข้อโต้แย้งโฆษณา
Ben Thul

5
ฉันเห็นด้วยกับการโต้แย้งของคุณอย่างแน่นอน เมื่อมองตามมูลค่าแล้ว OP กำลังทำสิ่งที่ผิดอย่างแน่นอน แต่อาจมีความต้องการที่ลึกกว่านั้นไม่ได้ระบุไว้ในโพสต์ว่า OP ไม่คิดว่าเกี่ยวข้องกับการได้รับคำตอบของคำถาม ดังนั้นจงตอบคำถามและให้คำแนะนำ "สิ่งที่ควรทำและไม่ควรทำ" ซึ่งเป็นส่วนหนึ่งของคำตอบ โดยวิธีการที่ฉันไม่เคยโจมตีตัวละครของคุณ ... ad hominem หมายความว่าฉันเรียกคุณว่าโง่หรืออะไร ...
Serj Sagan

1
แม้ว่าจะเป็นจริงในกรณีส่วนใหญ่มีสถานการณ์ที่ถูกต้องตามกฎหมายในการ re-seed ตาราง ตัวอย่างเช่นฉันกำลังทำงานในโครงการกรีนฟิลด์ที่ต้องเริ่มจากจุดที่แน่นอนเพื่อพิจารณาแถวที่มีอยู่ในรุ่นก่อนที่มีการแทนที่ Reseeding ระหว่างการพัฒนาเป็นกรณีการใช้งานที่ถูกกฎหมาย IMO
David A. Grey

3

เรียกใช้สคริปต์นี้เพื่อรีเซ็ตคอลัมน์ข้อมูลประจำตัว คุณจะต้องทำการเปลี่ยนแปลงสองครั้ง แทนที่ tableXYZ ด้วยตารางที่คุณต้องการอัปเดต นอกจากนี้ชื่อของคอลัมน์ข้อมูลประจำตัวต้องลดลงจากตารางอุณหภูมิ สิ่งนี้เกิดขึ้นทันทีบนโต๊ะที่มี 35,000 แถวและ 3 คอลัมน์ เห็นได้ชัดว่าสำรองข้อมูลตารางและลองสิ่งนี้ในสภาพแวดล้อมการทดสอบก่อน


select * 
into #temp
From tableXYZ

set identity_insert tableXYZ ON

truncate table tableXYZ

alter table #temp drop column (nameOfIdentityColumn)

set identity_insert tableXYZ OFF

insert into tableXYZ
select * from #temp

3
สิ่งนี้ไม่ถูกต้องทั้งหมด: SET IDENTITY_INSERT อยู่ผิดที่ มันไม่ได้ไปรอบ ๆ TRUNCATE แต่จะไปรอบ ๆ INSERT INTO (ดังนั้น identity_ INSERT ) นอกจากนี้จะใช้เฉพาะเมื่อข้อมูลที่เป็นความต้องการที่จะเก็บไว้ที่อื่นก็จะไม่มีประสิทธิภาพมากเมื่อเทียบกับเพียงแค่เรียกใช้คำสั่งตัดเดียว
โซโลมอน Rutzky

1
DBCC CHECKIDENT (<TableName>, reseed, 0)

นี่จะตั้งค่าตัวตนปัจจุบันเป็น 0

ในการแทรกค่าถัดไปค่าเอกลักษณ์จะเพิ่มขึ้นเป็น 1


1

ใช้ขั้นตอนที่เก็บไว้นี้:

IF (object_id('[dbo].[pResetIdentityField]') IS NULL)
  BEGIN
    EXEC('CREATE PROCEDURE [dbo].[pResetIdentityField] AS SELECT 1 FROM DUMMY');
  END
GO

SET  ANSI_NULLS ON
GO
SET  QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[pResetIdentityField]
  @pSchemaName NVARCHAR(1000)
, @pTableName NVARCHAR(1000) AS
DECLARE @max   INT;
DECLARE @fullTableName   NVARCHAR(2000) = @pSchemaName + '.' + @pTableName;

DECLARE @identityColumn   NVARCHAR(1000);

SELECT @identityColumn = c.[name]
FROM sys.tables t
     INNER JOIN sys.schemas s ON t.[schema_id] = s.[schema_id]
     INNER JOIN sys.columns c ON c.[object_id] = t.[object_id]
WHERE     c.is_identity = 1
      AND t.name = @pTableName
      AND s.[name] = @pSchemaName

IF @identityColumn IS NULL
  BEGIN
    RAISERROR(
      'One of the following is true: 1. the table you specified doesn''t have an identity field, 2. you specified an invalid schema, 3. you specified an invalid table'
    , 16
    , 1);
    RETURN;
  END;

DECLARE @sqlString   NVARCHAR(MAX) = N'SELECT @maxOut = max(' + @identityColumn + ') FROM ' + @fullTableName;

EXECUTE sp_executesql @stmt = @sqlString, @params = N'@maxOut int OUTPUT', @maxOut = @max OUTPUT

IF @max IS NULL
  SET @max = 0

print(@max)

DBCC CHECKIDENT (@fullTableName, RESEED, @max)
go

--exec pResetIdentityField 'dbo', 'Table'

เพียงแค่คำตอบของฉันกลับมาอีกครั้ง ฉันเจอพฤติกรรมแปลก ๆ ใน sql server 2008 r2 ที่คุณควรระวัง

drop table test01

create table test01 (Id int identity(1,1), descr nvarchar(10))

execute pResetIdentityField 'dbo', 'test01'

insert into test01 (descr) values('Item 1')

select * from test01

delete from test01

execute pResetIdentityField 'dbo', 'test01'

insert into test01 (descr) values('Item 1')

select * from test01

เลือกแรกผลิต 0, Item 1ครั้งแรกที่เลือกผลิต

1, Item 1คนที่สองผลิต หากคุณดำเนินการรีเซ็ตทันทีหลังจากตารางถูกสร้างขึ้นค่าถัดไปคือ 0 จริงๆแล้วฉันไม่แปลกใจเลยที่ Microsoft ไม่สามารถทำสิ่งนี้ให้ถูกต้องได้ ฉันค้นพบมันเพราะฉันมีไฟล์สคริปต์ที่เติมตารางการอ้างอิงที่บางครั้งฉันทำงานหลังจากที่ฉันสร้างตารางขึ้นใหม่และบางครั้งเมื่อตารางถูกสร้างขึ้นแล้ว


1

ฉันใช้สคริปต์ต่อไปนี้เพื่อทำสิ่งนี้ มีเพียงสถานการณ์เดียวที่จะสร้าง "ข้อผิดพลาด" ซึ่งถ้าคุณลบแถวทั้งหมดออกจากตารางและIDENT_CURRENTตั้งค่าปัจจุบันเป็น 1 นั่นคือมีเพียงแถวเดียวในตารางที่จะเริ่มต้นด้วย

DECLARE @maxID int = (SELECT MAX(ID) FROM dbo.Tbl)
;

IF @maxID IS NULL
    IF (SELECT IDENT_CURRENT('dbo.Tbl')) > 1
        DBCC CHECKIDENT ('dbo.Tbl', RESEED, 0)
    ELSE
        DBCC CHECKIDENT ('dbo.Tbl', RESEED, 1)
    ;
ELSE
    DBCC CHECKIDENT ('dbo.Tbl', RESEED, @maxID)
;

0

สำหรับแถว DELETE ที่สมบูรณ์และรีเซ็ตจำนวน IDENTITY ฉันใช้สิ่งนี้ (SQL Server 2008 R2)

USE mydb

-- ##################################################################################################################
-- DANGEROUS!!!! USE WITH CARE
-- ##################################################################################################################

DECLARE
  db_cursor CURSOR FOR
    SELECT TABLE_NAME
      FROM INFORMATION_SCHEMA.TABLES
     WHERE TABLE_TYPE = 'BASE TABLE'
       AND TABLE_CATALOG = 'mydb'

DECLARE @tblname VARCHAR(50)
SET @tblname = ''

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @tblname

WHILE @@FETCH_STATUS = 0
BEGIN
  IF CHARINDEX('mycommonwordforalltablesIwanttodothisto', @tblname) > 0
    BEGIN
      EXEC('DELETE FROM ' + @tblname)
      DBCC CHECKIDENT (@tblname, RESEED, 0)
    END

  FETCH NEXT FROM db_cursor INTO @tblname
END

CLOSE db_cursor
DEALLOCATE db_cursor
GO

0

การป้อนค่าเป็น 0 จะไม่สามารถใช้งานได้จริงนอกเสียจากว่าคุณจะทำความสะอาดโต๊ะโดยรวม

ฉลาดคำตอบที่ได้รับจากแอนโธนีเรย์มอนด์ก็สมบูรณ์แบบ รับคอลัมน์ข้อมูลประจำตัวสูงสุดก่อนจากนั้นจึงสร้างด้วยจำนวนสูงสุด


0

ฉันพยายามทำสิ่งนี้ให้สำเร็จสำหรับตารางจำนวนมากในระหว่างการพัฒนาและมันก็ใช้งานได้ดี

DBCC CHECKIDENT('www.newsType', RESEED, 1);
DBCC CHECKIDENT('www.newsType', RESEED);

ดังนั้นก่อนอื่นคุณต้องบังคับให้มันถูกตั้งค่าเป็น 1 จากนั้นคุณตั้งเป็นดัชนีสูงสุดของแถวที่มีอยู่ในตาราง ส่วนที่เหลืออย่างรวดเร็วและง่ายดายของ idex


-2

มันจะดีกว่าเสมอในการใช้ TRUNCATEเมื่อเป็นไปได้แทนที่จะลบระเบียนทั้งหมดเนื่องจากไม่ได้ใช้พื้นที่บันทึก

ในกรณีที่เราต้องการลบและจำเป็นต้องรีเซ็ตเมล็ดโปรดจำไว้เสมอว่าถ้าตารางไม่เคยมีการเติมข้อมูลและคุณใช้DBCC CHECKIDENT('tablenem',RESEED,0) แล้วบันทึกแรกจะได้รับเอกลักษณ์ = 0 ตามที่ระบุไว้ใน เอกสาร MSDN

ในกรณีของคุณเพียงสร้างดัชนีใหม่และไม่ต้องกังวลกับการสูญเสียชุดข้อมูลประจำตัวเนื่องจากนี่เป็นสถานการณ์ทั่วไป


3
ฟังดูฉันชอบความคิดที่จะลบเฉพาะบางระเบียน
Drumbeg

6
นี่เป็นเพียงข้อผิดพลาดธรรมดา - ไม่ใช่ <i> เสมอ </i> ดีกว่าที่จะใช้การตัดทอนและในความเป็นจริงแล้วจะดีกว่าในบางสถานการณ์ที่ จำกัด และเฉพาะเจาะจงเท่านั้น สวรรค์ห้ามมิให้ใครบางคนทำตามคำแนะนำของคุณแล้วต้องย้อนกลับ
Thronk

1
@Thronk ทำไมคุณถึงบอกว่าTRUNCATEจะป้องกันไม่ให้ROLLBACKทำงานตามที่คาดไว้ ROLLBACK ยังคงย้อนกลับ แม้ว่า DB BULK_LOGGEDมีการตั้งค่า
โซโลมอน Rutzky

2
TRUNCATE เป็นการดำเนินการ DDL และไม่ได้ลงชื่อเข้าใช้ในล็อกไฟล์ เว้นแต่จะเป็นส่วนหนึ่งของการทำธุรกรรม (ไม่ได้กล่าวถึงในคำถามหรือในคำตอบนี้) เมื่อใดก็ตามที่ใครบางคนบอกว่าบางสิ่งบางอย่างเป็นจริงเสมอมันเป็นเดิมพันที่ปลอดภัยที่พวกเขาผิด
Thronk

นี่เป็นคำตอบเดียวที่บันทึกมีความแตกต่างในพฤติกรรม RESEED ขึ้นอยู่กับว่าเคยใช้ลำดับมาก่อนหรือไม่ reseed ของค่าเดียวกันในหลายตารางที่ว่างเปล่าซึ่งบางตารางถูกเติมก่อนหน้านี้จะส่งผลให้ค่าเริ่มต้นที่แตกต่างกันสำหรับการบันทึกแรกแทรกลงในแต่ละตาราง
simon coleman

-4

ครั้งแรก: ข้อมูลจำเพาะเกี่ยวกับผู้ใช้เพียง: "ไม่" >> บันทึกโครงการดำเนินการฐานข้อมูล

หลังจากนั้น: ข้อมูลจำเพาะของผู้ใช้เพียง: "ใช่" >> บันทึกโครงการดำเนินการฐานข้อมูล

ID ฐานข้อมูลของคุณ, PK เริ่มจาก 1 >>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.