返回插入到标识列中的值(SCOPE_IDENTITY, IDENT_CURRENT 和 @@IDENTITY)

by Kimi 9. November 2009 16:09

Kimi

    在写SQL的时候,我们经常会遇到一种情况。那就是一个表中的某个列是自增的标识列,在插入记录到这个表后,我们需要返回这个标识列的值。

    我们通常都会习惯性的使用@@IDENTITY 来获得这个值。其实SQL Server 不只提供一个@@IDENTITY这个一个方式来获得新插入自增标识列的值,还有 SCOPE_IDENTITYIDENT_CURRENT 这两个函数。下面我们就来看看这个3个函数的区别,以及我们如何正确的选用它们。

    下面先给出MSDN上对这3个函数的描述:

@@IDENTITY

    返回最后插入的标识值的系统函数

备注:

    在一条 INSERT、SELECT INTO 或大容量复制语句完成后,@@IDENTITY 中包含语句生成的最后一个标识值。如果语句未影响任何包含标识列的表,则 @@IDENTITY 返回 NULL。如果插入了多个行,生成了多个标识值,则 @@IDENTITY 将返回最后生成的标识值。如果语句触发了一个或多个触发器,该触发器又执行了生成标识值的插入操作,那么,在语句执行后立即调用 @@IDENTITY 将返回触发器生成的最后一个标识值。如果对包含标识列的表执行插入操作后触发了触发器,并且触发器对另一个没有标识列的表执行了插入操作,则 @@IDENTITY 将返回第一次插入的标识值。出现 INSERT 或 SELECT INTO 语句失败或大容量复制失败,或者事务被回滚的情况时,@@IDENTITY 值不会恢复为以前的设置。

 

SCOPE_IDENTITY()

    返回插入到同一作用域中的标识列内的最后一个标识值。一个范围是一个模块:存储过程、触发器、函数或批处理。因此,如果两个语句处于同一个存储过程、函数或批处理中,则它们位于相同的作用域中。

备注:

    SCOPE_IDENTITY 和 @@IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值。但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值;@@IDENTITY 不受限于特定的作用域。

 

IDENT_CURRENT

    返回为某个会话和作用域中指定的表或视图生成的最新的标识值。

备注:

    IDENT_CURRENT 返回为某个会话和用域中的指定表生成的最新标识值。在空表中调用 IDENT_CURRENT 函数时,此函数将返回 NULL。

 

    从MSDN上看,这3个函数的主要区别就是一个会话和作用域的问题:

  • IDENT_CURRENT 返回为某个会话和用域中的指定表生成的最新标识值。
  • @@IDENTITY 返回为跨所有作用域的当前会话中的某个表生成的最新标识值。
  • SCOPE_IDENTITY 返回为当前会话和当前作用域中的某个表生成的最新标识值。

 

    接下来,我们需要通过示例来看看这个3个函数的区别

-- 创建一个表TA, 为它定义一个自增列ID, 默认这个列是从开始自增.

CREATE TABLE TA(ID int IDENTITY);

-- 创建另一个表TB, 为它定义一个自增列ID, 设置这个列是从开始自增.

CREATE TABLE TB(ID int IDENTITY(100,1));

GO

-- 为表TA 创建一个INSERT的出发器,让给TA 表插入数据后, 给TB 表也插入数据.

CREATE TRIGGER TA_INSERT ON TA FOR INSERT

AS

BEGIN

INSERT TB DEFAULT VALUES

END;

GO

 

SELECT * FROM TA;

--ID is empty.

 

SELECT * FROM TB;

--ID is empty.

 

-- 在一个会话(session)中运行这些语句. --------------------

-- 向TA表插入一条默认记录.

INSERT TA DEFAULT VALUES;

SELECT @@IDENTITY;

/* 返回的值是100. 因为使用的是@@IDENTITY, 它得到的结果是触发器执行的插入数据到TB表后返回的标识列的值.*/

 

SELECT SCOPE_IDENTITY();

/* 返回的值是1. 因为向TA表插入的一条记录, 然而SCOPE_IDENTITY()是不能垮作用域的,那么它只获得插入TA表操作时返回的标识列的值.*/

 

SELECT IDENT_CURRENT('TB');

/* 返回插入TB表的标识列的值, 100.*/

 

SELECT IDENT_CURRENT('TA');

/* 返回插入TA表的标识列的值, 1.*/

 

-- 在另一个会话(session)中运行这些语句.

SELECT @@IDENTITY;

/* 返回的是NULL, 因为当前会话(session)中没有插入操作.*/

 

SELECT SCOPE_IDENTITY();

/* 返回的是NULL, 因为当前会话(session)当前作用域中没有插入操作*/

 

SELECT IDENT_CURRENT('TB');

/* 返回最后插入TB表的标识列的值, 100.*/

 

注意的一点是,作用域指的是一个模块:存储过程、触发器、函数或批处理。因此,如果两个语句处于同一个存储过程、函数或批处理中,则它们位于相同的作用域中。我们来看一个示例:

-- 创建一个存储过程, 其功能就是往TA表插入一条记录

CREATE PROCEDURE usp_ins_TA

AS

BEGIN

    INSERT TA DEFAULT VALUES;

END

 

-- 插入一条记录到TA表.

INSERT TA DEFAULT VALUES;

-- 调用存储过程插入一条记录到TA表.

EXECUTE usp_ins_TA;

 

SELECT @@IDENTITY;

/* 返回的结果是2, 因为执行了两次插入操作. */

 

SELECT SCOPE_IDENTITY();

/* 返回的结果是1, 因为尽管执行了两次操作, 但是第二次操作是调用一个存储过程, 那么它属于另一个范围内. */

 

SELECT IDENT_CURRENT('TA');

/* 返回的结果是2, 因为执行了两次插入操作. */

 

通过这两个示例,我想大家应该明白了这个3个函数的用法。(Kimi 2009-03-25)

Tags:

技术文章

Comments

8/3/2010 2:39:34 AM #

high blood pressure diet chart

How is hypertension measuredIJAt just about every prenatal go to  the wellbeing caution supplier measures blood pressure level with an inflatable cuff that wraps all-around the

high blood pressure diet chart | Reply

Add comment


(Will show your Gravatar icon)

biuquote
  • Comment
  • Preview
Loading



Copyright © 2009 APJ Software

最新评论

Comment RSS

公告

欢迎使用APJ Blog!

日历

<<  September 2010  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar