增加一条新记录,同时返回其自增id
方法一、是在Insert或Update触发器中用select来返回需要的字段值。默认情况下,当insert时,触发其insert触发器,它的默认返回值是影响到的行数,语句是:select @@rowcount。如果利用insert和update触发器中的一个技巧,那就是“当insert时,数据库会生成一个临时表,就是inserted表;这个表会记录刚刚要插入的信息,insert完,它就消失了,我们只需select art_id from inserted就会返回刚刚插入的这条记录的art_id了”。同理,“在update时,会生成deleted与inserted两个临时表,一个是修改前数据,一个是修改后数据;我们只需在update触发器写一条select * from inserted就可以了(返回修改后的记录)”。那么就可以轻松的用一条insert或update语句来实现自增一个字段并取回自增前/后的值。
需要注意的是文章中指出在触发器中可以返回一个记录集,但是不支持大量的输出文本,这一点比较含糊,何为大量?文本又是指何种字段?
2long sn = long.Parse(db.GetDs(sql).Tables[0].Rows[0]["Process_lastno"].ToString());
然后是tbProcesses表的Update触发器:
2FOR UPDATE
3AS
4select Process_lastno from inserted
5
说起来似乎有些复杂,但是实现还是蛮简单的,尤其是一步到位,不需要用到锁和事务。
方法二:
在SQL Server中identity列是自动增量的列,每次插入新的列时该列会自动填入新的唯一值,在许多应用中需要在插入一条记录的之后获得刚插入记录的identity列的值,许多网站介绍了在插入后立刻执行@@identity等值即函数的查询,但是那都是在同一个session下的T-SQL,在一个存储过程中是可以用的,但是在C#中,如果用SqlDataAdapter的Fill方法来做就比较麻烦了。今晚尝试了一下,在系统特定需求下实现了获取identity列的新增值。
2 sql += "'" + LogName + "'";
3 sql += ",'" + Password + "'";
4 sql += ")";
5 DataSet ds = oDB.GetDs(sql + ";select SCOPE_IDENTITY() as id");
6 string id = ds.Tables[0].Rows[0]["id"].ToString();
其中第5行的GetDs函数如下:
2 {
3 Open();
4 SqlDataAdapter Ada = new SqlDataAdapter(str_Sql,cn);
5 DataSet ds = new DataSet();
6 Ada.Fill(ds);
7 cn.Close();
8 return ds;
9 }
此外,SCOPE_IDENTITY功能类似的还有IDENT_CURRENT 和 @@IDENTITY,因为它们都返回插入到 IDENTITY 列中的值。
IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 返回为任何会话和作用域中的特定表所生成的值。有关更多信息,请参见 IDENT_CURRENT。
SCOPE_IDENTITY 和 @@IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值。但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值;@@IDENTITY 不受限于特定的作用域。
网上文章参考:
这个问题的原意的是这样的:
数据表中,主键为自增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触发器,而很多时候,例如编辑文章时,我们无需返回当前记录,只是在显示文章时需要返回罢了,这个问题,在使用时根据具体情况采用吧。
作者: 王春天 出处: http://www.cnblogs.com/spring_wang/ Email: spring_best@yeah.net QQ交流:903639067
QQ群:322581894 关于作者: 大连天翼信息科技有限公司 技术总监。 SNF快速开发平台 创始人。应用平台架构师、IT规划咨询专家、业务流程设计专家。 专注于快速开发平台的开发、代码生成器。同时专注于微软平台项目架构、管理和企业解决方案,多年项目开发与管理经验,精通DotNet系列技术Vue、.NetCore、MVC、Webapi、C#、WinForm等,DB(SqlServer、Oracle等)技术,移动端开发。熟悉Java、VB及PB开发语言。在面向对象、面向服务以及数据库领域有一定的造诣。现从事项目实施、开发、架构等工作。并从事用友软件产品U8、U9、PLM 客开工作。 如有问题或建议,请多多赐教! 本文版权归作者和CNBLOGS博客共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过邮箱或QQ 联系我,非常感谢。