ตัวเลือกใดเป็นตัวเลือกที่ดีที่สุดในการรับค่าตัวตนที่ฉันเพิ่งสร้างผ่านการแทรก อะไรคือผลกระทบของแถลงการณ์เหล่านี้ในแง่ของประสิทธิภาพ?
SCOPE_IDENTITY()
- ฟังก์ชันการรวม
MAX()
- SELECT
TOP 1
IdentityColumn จาก TableNameORDER BY IdentityColumn DESC
ตัวเลือกใดเป็นตัวเลือกที่ดีที่สุดในการรับค่าตัวตนที่ฉันเพิ่งสร้างผ่านการแทรก อะไรคือผลกระทบของแถลงการณ์เหล่านี้ในแง่ของประสิทธิภาพ?
SCOPE_IDENTITY()
MAX()
TOP 1
IdentityColumn จาก TableNameORDER BY IdentityColumn DESC
คำตอบ:
ใช้SCOPE_IDENTITY()
หากคุณกำลังแทรกแถวเดียวและต้องการดึง ID ที่ถูกสร้างขึ้น
CREATE TABLE #a(identity_column INT IDENTITY(1,1), x CHAR(1));
INSERT #a(x) VALUES('a');
SELECT SCOPE_IDENTITY();
ผล:
----
1
ใช้ส่วนOUTPUT
คำสั่งหากคุณกำลังแทรกหลายแถวและจำเป็นต้องดึงชุด ID ที่สร้างขึ้นมา
INSERT #a(x)
OUTPUT inserted.identity_column
VALUES('b'),('c');
ผล:
----
2
3
และทำไมตัวเลือกนี้ถึงเร็วที่สุด
นอกเหนือจากประสิทธิภาพแล้วสิ่งเหล่านี้เป็นสิ่งเดียวที่รับประกันได้ว่าถูกต้องในระดับการแยกเริ่มต้นและ / หรือมีผู้ใช้หลายคน แม้ว่าคุณจะเพิกเฉยต่อความถูกต้อง แต่ SQL Server ยังคงมีค่าที่แทรกอยู่SCOPE_IDENTITY()
ในหน่วยความจำดังนั้นโดยปกติแล้วสิ่งนี้จะเร็วกว่าการไปและเรียกใช้แบบสอบถามแบบแยกเดี่ยวของคุณกับตารางหรือจากตารางระบบ
การเพิกเฉยต่อความถูกต้องนั้นก็เหมือนกับการบอกพนักงานส่งจดหมายว่าเขาทำงานได้ดีในการส่งจดหมายของวันนี้ - เขาเสร็จสิ้นเส้นทางของเขาเร็วกว่าเวลาเฉลี่ย 10 นาทีปัญหาคือไม่มีจดหมายใดถูกส่งไปยังบ้านที่ถูกต้อง
อย่าใช้สิ่งใดสิ่งหนึ่งต่อไปนี้:
@@IDENTITY
- เนื่องจากสิ่งนี้ไม่สามารถใช้ได้ในทุกสถานการณ์ตัวอย่างเช่นเมื่อตารางที่มีคอลัมน์ข้อมูลประจำตัวมีทริกเกอร์ที่แทรกเข้าไปในตารางอื่นด้วยคอลัมน์ข้อมูลประจำตัวของมันเอง - คุณจะได้รับค่าที่ไม่ถูกต้องกลับมาIDENT_CURRENT()
- ฉันได้ลงรายละเอียดเกี่ยวกับเรื่องนี้ที่นี่และความเห็นก็เป็นประโยชน์สำหรับการอ่านเช่นกัน แต่โดยพื้นฐานแล้วคุณจะได้รับคำตอบที่ผิดMAX()
หรือTOP 1
- คุณจะต้องปกป้องทั้งสองข้อความด้วยการแยกแบบแยกได้เพื่อให้แน่ใจว่าMAX()
คุณได้รับไม่ใช่คนอื่น SCOPE_IDENTITY()
นี่คือราคาแพงกว่าเพียงแค่ใช้ฟังก์ชั่นเหล่านี้ล้มเหลวเมื่อใดก็ตามที่คุณแทรกสองแถวขึ้นไปและต้องการค่าเอกลักษณ์ทั้งหมดที่สร้างขึ้น - ตัวเลือกเดียวของคุณคือส่วนOUTPUT
คำสั่ง
นอกเหนือจากการแสดงแล้วพวกเขาทั้งหมดมีความหมายแตกต่างกันมาก
SCOPE_IDENTITY()
จะให้คุณระบุค่าตัวตนสุดท้ายลงในตารางใด ๆโดยตรงภายในขอบเขตปัจจุบัน (scope = batch, กระบวนงานที่เก็บไว้, ฯลฯ แต่ไม่ได้อยู่ภายใน, พูด, ทริกเกอร์ที่ถูกไล่ออกจากขอบเขตปัจจุบัน)
IDENT_CURRENT()
จะให้ค่าตัวตนสุดท้ายแทรกลงในตารางที่เฉพาะเจาะจงจากใด ๆขอบเขตโดยใด ๆของผู้ใช้
@@IDENTITY
ให้ค่าตัวตนล่าสุดที่สร้างโดยคำสั่ง INSERT ล่าสุดสำหรับการเชื่อมต่อปัจจุบันโดยไม่คำนึงถึงตารางหรือขอบเขต (หมายเหตุด้าน: Access ใช้ฟังก์ชันนี้และมีปัญหาบางอย่างเกี่ยวกับทริกเกอร์ที่แทรกค่าลงในตารางที่มีคอลัมน์ข้อมูลประจำตัว)
การใช้MAX()
หรือTOP 1
สามารถให้ผลลัพธ์ที่ผิดทั้งหมดถ้าตารางมีขั้นตอนการลบข้อมูลประจำตัวหรือมีการแทรกแถวด้วยSET IDENTITY_INSERT
ในการเล่น นี่เป็นสคริปต์ที่แสดงให้เห็นถึงสิ่งเหล่านี้:
CREATE TABLE ReverseIdent (
id int IDENTITY(9000,-1) NOT NULL PRIMARY KEY CLUSTERED,
data char(4)
)
INSERT INTO ReverseIdent (data)
VALUES ('a'), ('b'), ('c')
SELECT * FROM ReverseIdent
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9000
SET IDENTITY_INSERT ReverseIdent ON
INSERT INTO ReverseIdent (id, data)
VALUES (9005, 'd')
SET IDENTITY_INSERT ReverseIdent OFF
SELECT IDENT_CURRENT('ReverseIdent') --8998
SELECT MAX(id) FROM ReverseIdent --9005
สรุป: ติดกับSCOPE_IDENTITY()
, IDENT_CURRENT()
หรือ@@IDENTITY
, และตรวจสอบให้แน่ใจว่าคุณกำลังใช้อันที่คืนสิ่งที่คุณต้องการจริง ๆ
IDENT_CURRENT()
และ@@IDENTITY
เมื่อสคริปต์ของคุณแสดงให้เห็นว่าพวกเขาแสดงผลลัพธ์ที่ไม่ถูกต้อง
IDENT_CURRENT()
ส่งคืน MAX () ไม่เคยส่งกลับค่าสิทธิเกินแถวแรกตั้งแต่ ID เป็นถอยหลังนับและด้วยความIDENTITY_INSERT
ที่ 9005 ไม่ได้เป็นที่สร้างIDENT_CURRENT()
ค่าตัวตนจึงไม่ได้สะท้อนจาก แต่มันอาจส่งคืนผลลัพธ์ที่ "ไม่ถูกต้อง" หากคุณเป็นคนจริงหลังจากสิ่งที่SCOPE_IDENTITY()
ส่งคืนแล้ว เลือกเครื่องมือที่เหมาะสมสำหรับงาน
@@IDENTITY
เกือบจะไม่เคยเป็นวิธีที่เหมาะที่จะได้รับค่าตัวตนที่สร้างขึ้น ประเด็นหลักคือMAX()
หรือTOP 1
เป็นเวอร์ชั่นที่น่าเชื่อถือน้อยกว่าIDENT_CURRENT()
ซึ่งเป็นฟังก์ชั่นที่สมบูรณ์แบบที่จะใช้หากคุณเข้าใจในสิ่งที่มันทำ อาจเป็นประโยชน์สำหรับงานบำรุงรักษาหรือบางสิ่งบางอย่าง