项目中有一个存储过程sp,向表A插入一条数据,表有INSTEAD OF INSERT触发器,在触发器中,有一条语句是向表A中插入的语句:
INSERT [A] SELECT I.[TCW_PKey] , I.[TCE_PKey] .... FROM [Inserted] AS I ....
现在想在触发器中的这条语句之后立即得到插入的主键值,用IDENT_CURRENT,那么并发插入会出问题,所以想用SCOPE_IDENTITY或者@@IDENTITY, 可是纠结的是, 在本地结果是正确的,也就是插入到[A]的主键值可是在服务器上却是其他表的主键,跟踪单用户运行也结果不正确,是表C的主键,哎,理论上这关表C什么事啊?当然,是在存储过程sp中在插入表A之前向表C插入了数据.
现在我的问题是,是数据库配置还是选项或者SP补丁影响了SCOPE_IDENTITY或者@@IDENTITY返回值?还是其他问题?希望有经验的朋友提示一下,感激不尽

解决方案 »

  1.   

    --2005用output try
    if object_id('tb')is not null drop table tb
    go
    create table tb(ID int identity,[name] varchar(10))
    insert tb
    output inserted.ID
    select 'test'
    insert tb
    output inserted.ID
    select 'test'
    /*
    ID
    -----------
    1ID
    -----------
    2*/ 
      

  2.   

    在一条 INSERT、SELECT INTO 或大容量复制语句完成后,@@IDENTITY 中包含此语句产生的最后的标识值。若此语句没有影响任何有标识列的表,则 @@IDENTITY 返回 NULL。若插入了多个行,则会产生多个标识值,@@IDENTITY 返回最后产生的标识值。如果此语句激发一个或多个执行产生标识值的插入操作的触发器,则语句执行后立即调用 @@IDENTITY 将返回由触发器产生的最后的标识值。若 INSERT 或 SELECT INTO 语句失败或大容量复制失败,或事务被回滚,则 @@IDENTITY 值不会还原为以前的设置。在返回插入到表的 @@IDENTITY 列的最后一个值方面,@@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 函数类似。 @@IDENTITY 和 SCOPE_IDENTITY 将返回在当前会话的所有表中生成的最后一个标识值。但是,SCOPE_IDENTITY 只在当前作用域内返回值,而 @@IDENTITY 不限于特定的作用域。IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 返回任何会话和任何作用域中为特定表生成的标识值。有关更多信息,请参见 IDENT_CURRENT。
      

  3.   

    PS:这个id要通过表变量或者表来获取
    if object_id('tb')is not null drop table tb
    go
    create table tb(ID int identity,[name] varchar(10))
    declare @t table(ID int)
    insert tb
    output inserted.ID into @t
    select 'test'
    insert tb
    output inserted.ID into @t
    select 'test'
    select * from @t
    /*
    ID
    -----------
    1
    2
    */
      

  4.   

    现在我的问题是,是数据库配置还是选项或者SP补丁影响了SCOPE_IDENTITY或者@@IDENTITY返回值?还是其他问题?希望有经验的朋友提示一下,感激不尽没人看的懂?
      

  5.   

    用IDENT_CURRENT,那么并发插入会出问题,
    @@IDENTITY 和 SCOPE_IDENTITY 将返回在当前会话的所有表中生成的最后一个标识值。但是,SCOPE_IDENTITY 只在当前作用域内返回值,而 @@IDENTITY 不限于特定的作用域。IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 返回任何会话和任何作用域中为特定表生成的标识值。有关更多信息,请参见 IDENT_CURRENT。楼主看一下是不是这个问题,你应该要用的IDENT_CURRENT,这个才仅限于表,其它的是所有表生成的标识
      

  6.   

    TO SQL77:你说的这些我当然知道,在触发器中的INSERT 之后 SCOPE_IDENTITY 和 @@IDENTITY 是不是应该返回上一条INSERT影响的主键?问题是,我在本地是正常的,服务器上不知道为什么就不正确?相同的存储过程和触发器
      

  7.   

    --(2)@@identity,scope_identiuty()之间的区别   
    /*  
    对于@@identity而言,它返回的是当前会话中任何作用域内的最后插入的一个标识值  
    对于scope_identity()而言,它返回的是当前作用域内插入的标识值  
    */  
    create table t1   
    (   
      id int identity(1,1),   
      col int  
    )   
    create table t2   
    (   
      id int identity(100,1),   
      col int  
    )   
    create trigger tg_t1 on t1   
    for insert   
    as    
    insert into t2 select col from inserted   
    go   
    insert into t1 select 2   
    select @@identity,scope_identity()   本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ws_hgo/archive/2009/02/10/3872714.aspx
      

  8.   

    在触发器中的INSERT 之后 SCOPE_IDENTITY 和 @@IDENTITY 是不是应该返回上一条INSERT影响的主键?
    我在本地是正常的,服务器上不知道为什么就不正确?相同的存储过程和触发器
      

  9.   

    create table t1   
    (   
      id int identity(1,1),   
      col int  
    )   
    create table t2   
    (   
      id int identity(100,1),   
      col int  
    )   
    create trigger tg_t1 on t1   
    for insert   
    as    
    insert into t2 select col from inserted   
    go   
    insert into t1 select 3 
      
    select @@identity,scope_identity()                                           
    --------------------------------------- ---------------------------------------
    101                                     2(1 行受影响)select * from t2id          col
    ----------- -----------
    100         2
    101         3(2 行受影响)
    select * from t1
    id          col
    ----------- -----------
    1           2
    2           3(2 行受影响)看我上面的代码
    scope_identity()是当前insert into t1 select 3 
    返回的ID
    而这个@@identity
    是所有表中最后返回的也就是触发器中针对t2插入的值
    101         3
      

  10.   

    SCOPE_IDENTITY 和 @@IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值如果你得到的是c的标示值,那说明.......
    要不你贴出你的整个语句看看吧
      

  11.   

    CREATE TABLE TZ (
       Z_id  int IDENTITY(1,1)PRIMARY KEY,
       Z_name varchar(20) NOT NULL)INSERT TZ
       VALUES ('Lisa')
    INSERT TZ
       VALUES ('Mike')
    INSERT TZ
       VALUES ('Carla')
    CREATE TABLE TY (
       Y_id  int IDENTITY(100,5)PRIMARY KEY,
       Y_name varchar(20) NULL)INSERT TY (Y_name)
       VALUES ('boathouse')
    INSERT TY (Y_name)
       VALUES ('rocks')
    INSERT TY (Y_name)
       VALUES ('elevator')SELECT * FROM TY
    --Result set: This is how TY looks:
    CREATE TRIGGER Ztrig
    ON TZ
    FOR INSERT AS 
       BEGIN
       INSERT TY VALUES ('')
       END
    INSERT TY VALUES ('bbbbb')INSERT TZ VALUES ('gggggg')SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]
    GO
    SELECT   @@IDENTITY AS [@@IDENTITY]
    GO
      

  12.   

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

  13.   


    在触发器里面:
    INSERT [A] SELECT I.[TCW_PKey] , I.[TCE_PKey] .... FROM [Inserted] AS I ....
    SET @PKEY = SCOPE_IDENTITY(); -- 或者 SET @PKEY = @@IDENTITY ; 这样写没错吧? 本机执行也是正确的,可是在服务器上执行就不正确,是C表的主键.
    为什么?
      

  14.   


    我早几天试过了..在tempdb里面执行结果和本地一样..,我现在去真实db中试试
      

  15.   

    简单点说,你的情况(任何表都可能有触发器),应该用
    SCOPE_IDENTITY,但是必须跟在insert语句后面,中间不能有任何其他语句
    或者麻烦点,用IDENT_CURRENT( 'table_name' ),注意不同地方的table_name是不同的,也要跟在insert语句后面
     
      

  16.   

    TO Yang_
     
    我当然知道跟在INSERT后面.原因是,本地服务器没有并发,而实际服务器有并发
    同一个会话,还并发? SCOPE_IDENTITY 不是当前会话的当前作用域么?
      

  17.   

    EXEC sp_helptrigger TTTTT
    看看A表上有什么触发器,这些触发器有没有向C插入数据。
      

  18.   

    TO ldslove即使有触发器也没影响吧?SCOPE_IDENTITY 不是当前会话的当前作用域么
      

  19.   

    疑难问题斑竹fcuandy
    你去问下他吧
    http://hi.csdn.net/fcuandy
      

  20.   

    以前是用IDENT_CURRENT,使用表级排他锁来阻止其他事务的并发插入,所以没问题,
    但你也知道,这样阻止并发,用户一多,被阻止的人就多了现在改成允许并发插入,从而需要改成SCOPE_IDENTITY ,可以本地可以,在服务器上就是错误的值,IDENT_CURRENT是正确,但是并发插入肯定有问题
      

  21.   

    你这个用法逻辑就有问题吧??在表A有INSTEAD OF INSERT触发器,但是在触发器内又向表A插入数据??
      

  22.   

    问题就是,你没说清你的用法    比如你的@@indentity  或是 scope_identity用到了什么地方。是在存储过程里,还是触发器里。在不同地方使用,得到的值可能是不同的。因为scope_identity是作用域范围的。比如,如果你在你的触发器内 select scope_identity,取得的就是触发器内返回的indentity;如果scope_identity用在你这个存储过程里,拿到的就不会是触发器indentity的值。
      

  23.   

    lsd 题目都不看清楚,我写的很清楚在触发器中,有一条语句是向表A中插入的语句:
    INSERT [A] SELECT I.[TCW_PKey] , I.[TCE_PKey] .... FROM [Inserted] AS I ....
    现在想在触发器中的这条语句之后立即得到插入的主键值,