Sự khác biệt giữa Scope_Identity (), Danh tính (), @@ Danh tính và Nhận dạng hiện tại () là gì?


191

Tôi biết Scope_Identity(), Identity(), @@Identity, và Ident_Current()tất cả có được giá trị của cột sắc, nhưng tôi rất thích biết sự khác biệt.

Một phần của tranh cãi mà tôi gặp phải là ý nghĩa của phạm vi được áp dụng cho các chức năng trên là gì?

Tôi cũng sẽ thích một ví dụ đơn giản về các kịch bản khác nhau của việc sử dụng chúng?


2
Đừng quên lỗi thực thi song song tồn tại trong SQL Server cho SCOPE_IDENTITY và @@ IDENTITY: support.microsoft.com/default.aspx?scid=kb;en-US;2019779
David d C e Freitas

@DaviddCeFreitas - Tôi tò mò muốn đọc về lỗi này, nhưng liên kết dường như bị hỏng (hoặc ít nhất, nó đang gây ra lỗi ASP).
rory.ap 7/07/2015

2
Trên thực tế, tôi đã tìm thấy nó: support.microsoft.com/en-us/kb/2019779
rory.ap 7/07/2015

Fix đã được phát hành như đã đề cập tại bài viết KB cũ đó
George Birbilis

Câu trả lời:


392
  • Các @@identityhàm trả về bản sắc cuối cùng được tạo ra trong cùng một phiên.
  • Các scope_identity()hàm trả về bản sắc cuối cùng được tạo ra trong cùng một phiên và phạm vi tương tự.
  • Trả ident_current(name)về danh tính cuối cùng được tạo cho một bảng hoặc dạng xem cụ thể trong bất kỳ phiên nào.
  • Các identity()chức năng không được sử dụng để có được một bản sắc, nó được sử dụng để tạo ra một bản sắc trong một select...intotruy vấn.

Phiên là kết nối cơ sở dữ liệu. Phạm vi là truy vấn hiện tại hoặc thủ tục lưu trữ hiện tại.

Một tình huống trong đó scope_identity()và các @@identitychức năng khác nhau, là nếu bạn có một kích hoạt trên bàn. Nếu bạn có một truy vấn chèn một bản ghi, khiến trình kích hoạt chèn một bản ghi khác ở đâu đó, scope_identity()hàm sẽ trả về danh tính được tạo bởi truy vấn, trong khi đó @@identityhàm sẽ trả về danh tính được tạo bởi trình kích hoạt.

Vì vậy, thông thường bạn sẽ sử dụng scope_identity()chức năng.


14
Tôi đã chọn đây là câu trả lời, vì đoạn "Một tình huống trong đó scope_identity () và đoạn @@ nhận dạng ...". Nó làm rõ mọi thứ hơn.
Tebo

1
Như David Freitas đã đề cập ở trên, có một lỗi trong việc triển khai scope_identity, vì vậy tôi khuyên bạn nên sử dụng một phương pháp thay thế, mệnh đề OUTPUT. Xem câu trả lời của tôi dưới đây.
Sebastian Meine

@Guffa - "Phiên là kết nối cơ sở dữ liệu". Phiên có được duy trì trên các kết nối nếu bạn đang sử dụng Kết nối nhóm không?
Dave Black

1
Đây là một câu trả lời mô hình vai trò. Cụ thể, làm việc với SQL và SQL Server có thể là lạ và điều này giải thích mọi thứ theo cách rất rõ ràng, của giáo dân, trong khi vẫn khá nhiều thông tin. Nó không giống như một cái gì đó được truyền đạt giữa hai chuyên gia cơ sở dữ liệu, điều mà rất nhiều câu trả lời SE khác làm.
Panzercrisis

@DaveBlack từ những gì tôi đọc: Không, phiên không được duy trì trong nhóm, phiên là duy nhất cho tập lệnh của bạn chạy sau khi kết nối (). Khi gộp ... PHP cho SQL Server sử dụng nhóm kết nối ODBC. Khi một kết nối từ nhóm được sử dụng, trạng thái kết nối được đặt lại. Đóng kết nối trả về kết nối đến nhóm. (lưu ý: xem nhận xét cho linux / mac) docs.microsoft.com/en-us/sql/connect/php/ mẹo
GDmac

42

Câu hỏi hay.

  • @@IDENTITY: trả về giá trị nhận dạng cuối cùng được tạo trên kết nối SQL của bạn (SPID). Hầu hết thời gian sẽ là những gì bạn muốn, nhưng đôi khi không phải như vậy (như khi một kích hoạt được kích hoạt để đáp ứng với một INSERT, và kích hoạt thực thi một INSERTtuyên bố khác ).

  • SCOPE_IDENTITY(): trả về giá trị nhận dạng cuối cùng được tạo trong phạm vi hiện tại (tức là thủ tục được lưu trữ, kích hoạt, hàm, v.v.).

  • IDENT_CURRENT(): trả về giá trị nhận dạng cuối cùng cho một bảng cụ thể. Không sử dụng điều này để nhận giá trị nhận dạng từ một INSERT, nó tùy thuộc vào điều kiện chủng tộc (nghĩa là nhiều kết nối chèn các hàng trên cùng một bảng).

  • IDENTITY(): được sử dụng khi khai báo một cột trong bảng dưới dạng cột định danh.

Để tham khảo thêm, hãy xem: http://msdn.microsoft.com/en-us/l Library / ms187342.aspx .

Để tóm tắt: nếu bạn đang chèn các hàng và bạn muốn biết giá trị của cột định danh cho hàng bạn vừa chèn, hãy luôn sử dụng SCOPE_IDENTITY().


16

Nếu bạn hiểu sự khác biệt giữa phạm vi và phiên thì sẽ rất dễ hiểu các phương thức này.

Một bài đăng blog rất hay của Adam Anderson mô tả sự khác biệt này:

Phiên có nghĩa là kết nối hiện tại đang thực thi lệnh.

Phạm vi có nghĩa là bối cảnh ngay lập tức của một lệnh. Mỗi cuộc gọi thủ tục được lưu trữ thực thi trong phạm vi riêng của nó và các cuộc gọi lồng nhau thực hiện trong một phạm vi lồng nhau trong phạm vi của thủ tục gọi. Tương tự, một lệnh SQL được thực thi từ một ứng dụng hoặc SSMS thực thi trong phạm vi của chính nó và nếu lệnh đó kích hoạt bất kỳ kích hoạt nào, thì mỗi kích hoạt sẽ thực thi trong phạm vi lồng nhau của chính nó.

Do đó, sự khác biệt giữa ba phương thức truy xuất danh tính như sau:

@@identitytrả về giá trị nhận dạng cuối cùng được tạo trong phiên này nhưng bất kỳ phạm vi nào .

scope_identity()trả về giá trị bản sắc cuối cùng được tạo trong này phiên và này phạm vi.

ident_current()trả về giá trị nhận dạng cuối cùng được tạo cho một bảng cụ thể trong bất kỳ phiên và bất kỳ phạm vi nào .


11

Phạm vi có nghĩa là bối cảnh mã thực hiện INSERTcâu lệnh SCOPE_IDENTITY(), trái ngược với phạm vi toàn cầu của @@IDENTITY.

CREATE TABLE Foo(
  ID INT IDENTITY(1,1),
  Dummy VARCHAR(100)
)

CREATE TABLE FooLog(
  ID INT IDENTITY(2,2),
  LogText VARCHAR(100)
)
go
CREATE TRIGGER InsertFoo ON Foo AFTER INSERT AS
BEGIN
  INSERT INTO FooLog (LogText) VALUES ('inserted Foo')
  INSERT INTO FooLog (LogText) SELECT Dummy FROM inserted
END

INSERT INTO Foo (Dummy) VALUES ('x')
SELECT SCOPE_IDENTITY(), @@IDENTITY 

Cho kết quả khác nhau.


9

Do lỗi được đề cập bởi @David Freitas và vì không tương thích với tính năng Sequence mới được giới thiệu vào năm 2012, tôi khuyên bạn nên tránh xa cả ba điều này. Thay vào đó, bạn có thể sử dụng mệnh đề OUTPUT để lấy giá trị nhận dạng được chèn. Ưu điểm khác là OUTPUT thậm chí hoạt động nếu bạn đã chèn nhiều hơn một hàng.

Để biết chi tiết và ví dụ xem tại đây: Khủng hoảng danh tính


Tôi nghĩ rằng câu trả lời này xứng đáng được chú ý nhiều hơn.
cheeze

Thật không may, INSERT ... OUTPUT Chèned.xx không hoạt động với các kích hoạt INSERT (tương tự với CẬP NHẬT ... OUTPUT Cập nhật.xx và kích hoạt CẬP NHẬT). Họ đề nghị sử dụng INSERT ... OUTPUT INTO nhưng nó quá dài dòng và sử dụng cái đó từ các máy khách (thay vì trong các procs được lưu trữ) là vấn đề. CHERTN ... OUTPUT Chèned.xx rất đẹp khi được sử dụng với các cuộc gọi phía máy khách (chỉ cần ExecuteScalar để chèn và nói lấy lại id được tạo tự động cho hàng mới) nếu bạn không cần kích hoạt.
George Birbilis

6

Để làm rõ vấn đề với @@Identity:

Chẳng hạn, nếu bạn chèn một bảng và bảng đó có các kích hoạt thực hiện chèn, @@Identitysẽ trả về id từ chèn trong kích hoạt (a log_idhoặc một cái gì đó), trong khiscope_identity() sẽ trả về id từ chèn trong bảng gốc.

Vì vậy, nếu bạn không có bất kỳ trình kích hoạt nào scope_identity()@@identitysẽ trả về cùng một giá trị. Nếu bạn có trình kích hoạt, bạn cần suy nghĩ về giá trị bạn thích.


4

Scope Identity: Danh tính của bản ghi cuối được thêm vào trong thủ tục được lưu trữ đang được thực thi.

@@Identity: Danh tính của bản ghi cuối được thêm vào trong lô truy vấn hoặc do kết quả của truy vấn, ví dụ: quy trình thực hiện thao tác chèn, sau đó kích hoạt trình kích hoạt sau đó chèn bản ghi sẽ trả về danh tính của bản ghi được chèn từ trình kích hoạt.

IdentCurrent: Danh tính cuối cùng được phân bổ cho bảng.


3

Đây là một lời giải thích tốt từ cuốn sách :

Đối với sự khác biệt giữa SCOPE_IDENTITY và @@ IDENTITY, giả sử rằng bạn có một thủ tục được lưu trữ P1 với ba câu lệnh:
- Một INSERT tạo ra một giá trị nhận dạng mới
- Một cuộc gọi đến một thủ tục được lưu trữ P2 cũng có một câu lệnh INSERT tạo ra một câu lệnh mới giá trị nhận dạng
- Một câu lệnh truy vấn các hàm SCOPE_IDENTITY và @@ IDENTITY Hàm SCOPE_IDENTITY sẽ trả về giá trị được tạo bởi P1 (cùng phiên và phạm vi). Hàm @@ IDENTITY sẽ trả về giá trị được tạo bởi P2 (cùng phiên không phân biệt phạm vi).

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.