【转】SQL 2008 Insert返回自动编号id三种方法比较
SQL Server 2008中,insert数据的时候返回自动编号的id,有三种方法实现SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY,
它们都返回插入到 IDENTITY 列中的值。
IDENT_CURRENT :返回为任何会话和任何作用域中的特定表最后生成的标识值。IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 返回为任何会话和作用域中的特定表所生成的值。
@@IDENTITY: 返回为当前会话的所有作用域中的任何表最后生成的标识值。
SCOPE_IDENTITY :返回为当前会话和当前作用域中的任何表最后生成的标识值
SCOPE_IDENTITY 和 @@IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值。但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值;@@IDENTITY 不受限于特定的作用域。
使用示例:
set @NewID=SCOPE_IDENTITY()
set @NewID=@@IDENTITY
set @NewID=IDENT_CURRENT('表名')
例如,有两个表 T1 和 T2,在 T1 上定义了一个 INSERT 触发器。当将某行插入 T1 时,触发器被激发,并在 T2 中插入一行。
此例说明了两个作用域:一个是在 T1 上的插入,另一个是作为触发器的结果在 T2 上的插入。
假设 T1 和 T2 都有 IDENTITY 列,@@IDENTITY 和 SCOPE_IDENTITY 将在 T1 上的 INSERT 语句的最后返回不同的值。
@@IDENTITY 返回插入到当前会话中任何作用域内的最后一个 IDENTITY 列值,该值是插入 T2 中的值。
SCOPE_IDENTITY() 返回插入 T1 中的 IDENTITY 值,该值是发生在相同作用域中的最后一个 INSERT。
如果在作用域中发生插入语句到标识列之前唤醒调用 SCOPE_IDENTITY() 函数,则该函数将返回 NULL 值。
而IDENT_CURRENT('T1') 和 IDENT_CURRENT('T2') 返回的值分别是这两个表最后自增的值。
ajqc的实验:(40条本地线程,40+40条远程线程同时并发测试,插入1200W行),得出的结论是:
1.在典型的级联应用中.不能用@@IDENTITY,在CII850,256M SD的机器上1W多行时就会并发冲突.在P42.8C,512M DDR上,才6000多行时就并发冲突.
2.SCOPE_IDENTITY()是绝对可靠的,可以用在存储过程中,连触发器也不用建,没并发冲突
=================================
@@IDENTITY与SCOPE_IDENTITY() 在一条 INSERT、SELECT INTO 或大容量复制语句完成后,
@@IDENTITY 中包含语句生成的最后一个标识值。
如果语句未影响任何包含标识列的表,则 @@IDENTITY 返回 NULL。
如果插入了多个行,生成了多个标识值,则 @@IDENTITY 将返回最后生成的标识值。
如果语句触发了一个或多个触发器,该触发器又执行了生成标识值的插入操作,那么,在语句执行后立即调用 @@IDENTITY 将返回触发器生成的最后一个标识值。
如果对包含标识列的表执行插入操作后触发了触发器,并且触发器对另一个没有标识列的表执行了插入操作,则 @@IDENTITY 将返回第一次插入的标识值。
出现 INSERT 或 SELECT INTO 语句失败或大容量复制失败,或者事务被回滚的情况时,@@IDENTITY 值不会恢复为以前的设置。
如果语句和事务失败,它们会更改表的当前标识,从而使标识列中的值出现不连贯现象。即使未提交试图向表中插入值的事务,也永远无法回滚标识值。
例如,如果因 IGNORE_DUP_KEY 冲突而导致 INSERT 语句失败,表的当前标识值仍然会增加。 @@IDENTITY、SCOPE_IDENTITY 和 IDENT_CURRENT 是相似的函数,因为他们都返回插入到表的 IDENTITY 列的最后一个值。 @@IDENTITY 和 SCOPE_IDENTITY 可以返回当前会话中的所有表中生成的最后一个标识值。但是,SCOPE_IDENTITY 只在当前作用域内返回值,而
@@IDENTITY 不限于特定的作用域。 IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。IDENT_CURRENT 可以返回任何会话和任何作用域中为特定表生成的标识值。 @@IDENTITY 函数的作用域是执行该函数的本地服务器上的当前会话。此函数不能应用于远程或链接服务器。若要获得其他服务器上的标识值,请在远程服务器或链接服务器上执行存储过程,并使(在远程或链接服务器的环境中执行的)该存储过程收集标识值,并将其返回本地服务器上的发出调用的连接。
以下示例向包含标识列 (LocationID) 的表中插入一行,并使用 @@IDENTITY 显示新行中使用的标识值:
USE AdventureWorks;
GO
--Display the value of LocationID in the last row in the table.
SELECT MAX(LocationID)
FROM Production.Location;
GO
INSERT INTO Production.Location (Name, CostRate, Availability, ModifiedDate)
VALUES ('Damaged Goods', 5, 2.5, GETDATE());
GO
SELECT @@IDENTITY AS 'Identity';
GO
--Display the value of LocationID of the newly inserted row.
SELECT MAX(LocationID) FROM Production.Location;
GO
补充:
我们要慎用@@IDENTITY,原因是 @@IDENTITY 它总是获取最后一条变更数据的自增字段的值, 而忽略了进行变更操作所在的范围约束。
比如,我有表 A 和表 B 两个表,现在我在表 A 上定义了一个Insert触发器,当在表 A 中插入一条数据时,自动在表 B 也插入一条数据。
此时,大家注意,有两个原子操作:在A中插入一条数据,接着在B中随后插入一条数据。
现在我们想下,假设上面表 A 和表 B 都有IDENTITY自增域,那么我们在表 A 插入一条数据后,使用了 SELECT @@IDENTITY 输出时,输出的到底是 A 还是 B 的自增域的值呢? 答案很明显,是谁最后插入就输出谁,那么就是 B 了。于是,我本意是想得到 A 的自增域值,结果得到了 B 的自增域值,一只 BUG 随之诞生,搞不好还会影响到整个系统数据的混乱。
因此,对于这种情况,建议大家慎用 @@IDENTITY,而尽量采用 SCOPE_IDENTITY() 函数替换之。SCOPE_IDENTITY() 也是得到最后一条自增域的值,但是它是仅限在一个操作范围之内,而不@@IDENTITY 是取全局操作的最后一步操作所产生的自增域的值的。 ==========================
@@IDENTITY SCOPE_IDENTITY()
2008-11-05 15:02 INSERT INTO Calculation_Option (Option_Type, VIP_Option_ID, Option_Code, Option_Description, Last_Updated_Date, Last_Updated_By)
VALUES (@Option_Type, @VIP_Option_ID, @Option_Code, @Option_Description, GetDate(), @Last_Updated_By)
SELECT @Option_ID = SCOPE_IDENTITY()
Calculation_Option这个表里面的option_Id是自动增长的,scope_identity()是为了得到自动增长后的值 这个地方用的是scope_Identity() 以下引用msdn
例如,有两个表 T1 和 T2,并且在 T1 上定义了 INSERT 触发器。当将某行插入 T1 时,触发器被激发,并在 T2 中插入一行。该方案演示了两个作用域:在 T1 上的插入,以及在 T2 通过触发器的插入。 假设 T1 和 T2 都有标识列,@@IDENTITY 和 SCOPE_IDENTITY 将在 T1 上的 INSERT 语句的最后返回不同的值。@@IDENTITY 将返回在当前会话中的任何作用域内插入的最后一个标识列的值。这是在 T2 中插入的值。SCOPE_IDENTITY() 将返回在 T1 中插入的 IDENTITY 值。这是在同一个作用域内发生的最后的插入。如果在任何 INSERT 语句作用于作用域中的标识列之前调用 SCOPE_IDENTITY() 函数,则该函数将返回空值。
=====================
CREATE TABLE #T(ID INT IDENTITY(1,1) PRIMARY KEY,NAME VARCHAR(20))
INSERT INTO #T SELECT 'A'
SELECT @@IDENTITY AS '@@IDENTITY',
SCOPE_IDENTITY() AS 'SCOPE_IDENTITY',
IDENT_CURRENT('#T') AS 'IDENT_CURRENT'
=====================
文章来自网络http://zhan.renren.com/codefans?gid=3602888497997187305&from=template&checked=true
【转】SQL 2008 Insert返回自动编号id三种方法比较的更多相关文章
- (转)在网页中JS函数自动执行常用三种方法
原文:http://blog.sina.com.cn/s/blog_6f6b4c3c0100nxx8.html 在网页中JS函数自动执行常用三种方法 在网页中JS函数自动执行常用三种方法 在HTML中 ...
- 在网页中JS函数自动执行常用三种方法
在网页中JS函数自动执行常用三种方法 在HTML中的Head区域中,有如下函数: <SCRIPT LANGUAGE="JavaScript"> function ...
- Postgresql 创建主键并设置自动递增的三种方法
Postgresql 有以下三种方法设置主键递增的方式,下面来看下相同点和不同点. --方法一create table test_a ( id serial, name character var ...
- 解决移动端浏览器 HTML 音频不能自动播放的三种方法
https://blog.csdn.net/PY0312/article/details/90349386 由于Android,IOS移动端的浏览器以及微信自带的浏览器为了用户更好的体验,规定不自动播 ...
- SQL SERVER2008及以上版本数据库自动备份的三种方法
方法一:创建一个维护计划对数据库进行备份 方法二:创建一个SQL作业对数据库进行备份 方法三:创建WINDOWS任务计划对数据库进行备份 方法一与方法二其实原理基本相同,都必需开启SQL代理服务,都会 ...
- 拦截iOS系统导航栏返回按钮事件-三种方法
方法一:在dealloc里面书写监听事件,因为只有pop才会调用dealloc,push不会掉用 - (void)dealloc {YLLog(@"123"); } 方法二:在- ...
- Win10怎么添加开机启动项?Win10添加开机自动运行软件三种方法
Win10管理开机启动项的方法相信大家已经非常熟悉,msconfig命令各系统都通用,那么很多用户发觉Win10和Win7 XP等系统不同,没有启动文件夹,那么我们怎么添加开机启动项呢?如晨软件或程序 ...
- 网页中JS函数自动执行常用三种方法
(1)最简单的调用方式,直接写到html的body标签里面: <body onload="myFunction()"></body> ...
- 第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据
第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据 ADO.NET 为什么要学习? 我们要搭建一个平台(Web/Winform ...
随机推荐
- null和空 not null
所谓的NULL就是什么都没有,连\0都没有,\0在字符串中是结束符,但是在物理内存是占空间的,等于一个字节,而NULL就是连这一个字节都没有.在 数据库里是严格区分的,任何数跟NULL进行运算都是NU ...
- [Effective C++ --032]确定你的public继承塑模出is-a
这一章都在讲述继承的关系.可以举个例子说明: 父类是水果,子类是苹果,苹果是一种(is-a)水果,但是水果不一定就是苹果. is-a并不是唯一存在classes之间的关系.另两个常见的关系是has-a ...
- Shell脚本调试工具set
可以使用set命令的x选项,显示所有命令执行及变量值的变化过程等. 具体使用方法:首先使用set -x开启调试模式,最后使用命令set +x关闭调试模式. 一个简单示例演示如何使用set命令进行脚本调 ...
- Type mytableview does not confirm to portocol UITableViewDataResource
继承UITableViewDataSource报上面这个总是,是重写协议时写错了 override func numberOfRowsInSection(section: Int) -> Int ...
- 【天池大数据赛题解析】资金流入流出预测(附Top4答辩ppt)
http://mp.weixin.qq.com/s?__biz=MzA3MDg0MjgxNQ==&mid=208451006&idx=1&sn=532e41cf020a0673 ...
- hadoop学习记录(二)HDFS java api
FSDateinputStream 对象 FileSystem对象中的open()方法返回的是FSDateInputStream对象,改类继承了java.io.DateInoutStream接口.支持 ...
- SQL Server 通配符 Wildcard character
SQL Server 通配符 Wildcard character % 任意长度的字符串,如:'%computer%' _ 单个字符,如:'_ean' [] ...
- Centos6.4最小化安装后使用xfce桌面环境
由于我个人使用的Centos是在虚拟机中最小化安装的,gnome实在是不喜欢,所以自己装了个xfce,安装后启动不起来,才发现x window等依赖环境没装,为了少走弯路,在此写下安装过程. 1.yu ...
- Linux中的crontab命令用法
Crontab 在linux中,crontab的用来设置定期执行指定的命令,我们可以用它来指定一些需要重复的事情,Linux系统的用户只需将想要定期要执行的命令序列加到crontab文件中,操作系统即 ...
- Adobe Edge Animate --使用HTML5实现手机摇一摇功能
Adobe Edge Animate --使用HTML5实现手机摇一摇功能 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权和原文地址. HTML5的发展日新月异,其功能 ...