Trong SQL Server, nếu bạn cần trả lại giá trị được tạo trong cột danh tính, bạn có một số tùy chọn. Mỗi tùy chọn này, mặc dù tương tự nhau, nhưng thực hiện một điều hơi khác nhau.
Đặc biệt, bạn có thể sử dụng các chức năng sau:
-
IDENT_CURRENT()
trả về giá trị nhận dạng được chèn cuối cùng cho một bảng nhất định. -
SCOPE_IDENTITY()
trả về giá trị nhận dạng cuối cùng được chèn vào cột nhận dạng trong bất kỳ trong phiên hiện tại và phạm vi hiện tại. -
@@IDENTITY
trả về giá trị nhận dạng được chèn cuối cùng trong bất kỳ trong phiên hiện tại, bất kể phạm vi.
Ví dụ
Dưới đây là một ví dụ chứng minh sự khác biệt giữa ba chức năng này.
Đầu tiên, tạo hai bảng. Lưu ý các giá trị gốc và giá trị gia tăng khác nhau đang được sử dụng cho cột nhận dạng trong mỗi bảng:
CREATE TABLE t1(id int IDENTITY(1,1)); CREATE TABLE t2(id int IDENTITY(150,10));
Bây giờ, hãy tạo một trình kích hoạt chèn một hàng vào bảng thứ hai bất cứ khi nào một hàng được chèn vào bảng đầu tiên:
CREATE TRIGGER t1_insert_trigger ON t1 FOR INSERT AS BEGIN INSERT t2 DEFAULT VALUES END;
Kích hoạt kích hoạt trong một phạm vi khác, vì vậy điều đó hoàn hảo cho ví dụ của tôi ở đây.
Chèn dữ liệu vào bảng đầu tiên, sau đó chọn kết quả từ cả hai bảng:
INSERT t1 DEFAULT VALUES; SELECT id AS t1 FROM t1; SELECT id AS t2 FROM t2;
Kết quả:
+------+ | t1 | |------| | 1 | +------+ (1 row affected) +------+ | t2 | |------| | 150 | +------+ (1 row affected)
Vì vậy, chỉ cần rõ ràng, dữ liệu này được chèn bởi hai phạm vi khác nhau. Phần chèn vào t1 đã được thực hiện bởi phạm vi hiện tại. Chèn vào t2 được thực hiện bởi trình kích hoạt, chạy trong một phạm vi khác.
Bây giờ chúng ta hãy chọn từ các chức năng đã đề cập trước đây:
SELECT @@IDENTITY AS [@@IDENTITY], SCOPE_IDENTITY() AS [SCOPE_IDENTITY()], IDENT_CURRENT('t1') AS [IDENT_CURRENT('t1')], IDENT_CURRENT('t2') AS [IDENT_CURRENT('t2')];
Kết quả:
+--------------+--------------------+-----------------------+-----------------------+ | @@IDENTITY | SCOPE_IDENTITY() | IDENT_CURRENT('t1') | IDENT_CURRENT('t2') | |--------------+--------------------+-----------------------+-----------------------| | 150 | 1 | 1 | 150 | +--------------+--------------------+-----------------------+-----------------------+
Kết quả được trả về bởi @@IDENTITY
không bị giới hạn ở phạm vi, và do đó nó trả về giá trị nhận dạng được chèn cuối cùng, bất kể phạm vi.
SCOPE_IDENTITY()
trả về giá trị nhận dạng từ bảng đầu tiên, vì đó là giá trị nhận dạng được chèn cuối cùng trong phạm vi hiện tại (trình kích hoạt nằm ngoài phạm vi hiện tại).
IDENT_CURRENT()
hàm chỉ trả về giá trị nhận dạng cuối cùng được chèn vào bảng được chỉ định, bất kể phạm vi hoặc phiên.
Mở một phiên mới
Bây giờ, đây là điều sẽ xảy ra nếu tôi mở một phiên mới và chạy lại câu lệnh trước đó:
USE Test; SELECT @@IDENTITY AS [@@IDENTITY], SCOPE_IDENTITY() AS [SCOPE_IDENTITY()], IDENT_CURRENT('t1') AS [IDENT_CURRENT('t1')], IDENT_CURRENT('t2') AS [IDENT_CURRENT('t2')];
Kết quả:
+--------------+--------------------+-----------------------+-----------------------+ | @@IDENTITY | SCOPE_IDENTITY() | IDENT_CURRENT('t1') | IDENT_CURRENT('t2') | |--------------+--------------------+-----------------------+-----------------------| | NULL | NULL | 1 | 150 | +--------------+--------------------+-----------------------+-----------------------+
Cả @@IDENTITY
và SCOPE_IDENTITY()
là NULL vì chúng chỉ trả về kết quả từ phiên hiện tại. Tôi chưa thực hiện bất kỳ lần chèn cột danh tính nào trong phiên mới này, vì vậy tôi nhận được NULL.
IDENT_CURRENT()
mặt khác, trả về kết quả tương tự như trong ví dụ trước vì kết quả của nó dựa trên bảng được chỉ định, bất kể phiên hoặc phạm vi.