保存一个记录到数据库又马上返回ID号

时间:2021-07-07 22:52:46

有的时候我们需要取得刚添加记录的id值,很多人都说用"select top 1 id from tablename order by id desc",这种方法大部分情况下是可行的,为什么是大部分呢?当数据库更新非常频繁时,可能你在执行insert后select前其他人也添加了新记录,那返回的值就不准确了。
 
在一条   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。  
   
  示例  
  下面的示例向带有标识列的表中插入一行,并用   @@IDENTITY   显示在新行中使用的标识值。  
   
  INSERT   INTO   jobs   (job_desc,min_lvl,max_lvl)  
  VALUES   ('Accountant',12,125)  
  SELECT   @@IDENTITY   AS   'Identity'
 
就是用这种插入马上又查询,立即返回ID,一样是可以的,不管你的软件是不是网络版,不管有多少的客户端同时操作同一个表,返回来的ID不会有错。因为这些我都测试过。SQLserver还是挻牛B的,哈哈。。

==========================================================================================

这个问题的原意的是这样的:
数据表中,主键为自增id,例如
[Art_Id] int IDENTITY(1,1) NOT NULL
当insert进入一条新记录时,返回这条新记录的art_id,前提是用一条sql语句,(如是用两条语句就不用讨论了,呵呵);

这个问题是一些公司的面试题,我来公司时,也被问到这个问题,我说不会,呵呵;

关于这个问题,我在网上搜了一下,没有太仔细的看,大多数是说不可能,或是用存储过程来解决(存储过程中也是写两句),我也没去深究,后来在工作中碰到这个问题了,研究了一下,得了一个方法,可以用一条insert语句来返回其当前记录的自增id,只是不知道这是不是最合格的答案。拿出来大家讨论讨论。

我用的数据库是Sql Server 2005;

利用了触发器;我在器发器中写一条sql语句;以后,每次insert就可以返回其id了,高手们估计已经猜到什么方法了;其实我这个方法也没有什么高明的,毕竟触发器是个特殊的存储过程罢了;

我还是先说一下我的思路吧;
大家都知道触发器这个玩意,默认情况下,当insert时,触发其insert触发器,它的默认返回值是影响到的行数,语句是:select @@rowcount
而当insert时,数据库会生成一个临时表,就是inserted表;这个表会记录刚刚要插入的信息,insert完,它就消失了,我们只需………
select art_id from inserted
就会返回刚刚插入的这条记录的art_id了;
大伙明白了吧,呵呵,是不是很简单;

写好了触发器,以后,我们只需insert into ……就可以了,它返回的值将不再是影响到的行数,而是当前记录的自增id了;

我这个方法,实现了一条Insert语句返回其自增id,但不是一条sql语句,因为在触发器里,多写了一条语句;不知道有没有更好的办法;

当我用了这个方法后,我又想到别一个可利用的地方,就是我们显示文章时,要使文章增加一次浏览量,一般会先select出单条文章,然后再update该文章的浏览量的字段,使其加一;这要两条语句实现;如何用一条语句实现呢,很简单啦,用update触发器喽;

思路是,在update触发器中写select语句,然后,在执行时,只需使用修改浏览量的语句,就会返回当前修改的记录,我把这条记录显示到程序中就行了,就实现了新闻的显示与浏览量加一。


不过要说明一下下了,update的操作,在数据库中,其实是删除记录,然后再增加记录,也就是说,在update时,会生成deleted与inserted两个临时表,一个是修改前数据,一个是修改后数据;
我们只需在update触发器写一条select * from inserted就可以了(返回修改后的记录),以后,update时,让文章的浏览数加一时,直接返回了这个文章,呵呵,不错吧;

但是,报错了,select * from inserted这条语句报错,看看为什么,原来它不支持大量的文本输出,而前面取id时,是select art_id from inserted,它只返回一个或一组数字,而现在是返回整篇文章;没办法呀,只好修正一下喽select * from article where art_id in (select art_id from inserted)
这样就可以了;

看来触发器还是蛮好玩的哟;

不过触发器还是慎用为好,例如上面的文章显示,所有的修改操作都会触发它的update触发器,而很多时候,例如编辑文章时,我们无需返回当前记录,只是在显示文章时需要返回罢了,这个问题,在使用时根据具体情况采用吧。