insert into select.....select @@IDENTITY 返回的时候是结果集?

当前访客身份:游客 [
:mainClass 这个是必须的吗? 我没有mian方法的类...
:楼主,想问一下提取出来的关键字有同义词怎么办?
:楼主,想问一下提取出来的关键字有同义词怎么办?
:楼主,想问一下提取出来的关键字有同义词怎么办?
:楼主,想问一下提取出来的关键字有同义词怎么办?
:引用来自“艮子明”的评论 引用来自“hkodk”的评...
:引用来自“于小龙”的评论tfs 的nodejs的客户端谁...
:tfs 的nodejs的客户端谁写过 请教个问题
:tfs nodejs 客户端 谁写过 请教一下
今日访问:344
昨日访问:437
本周访问:1231
本月访问:781
所有访问:166294
mysql插入数据后返回自增ID的方法
发表于2年前( 20:25)&&
阅读(5641)&|&评论()
0人收藏此文章,
mysql和oracle插入的时候有一个很大的区别是,oracle支持序列做id,mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得到这个自增id的值呢?
方法一是使用last_insert_id
mysql& SELECT LAST_INSERT_ID();
&&&&产生的ID 每次连接后保存在服务器中。这意味着函数向一个给定客户端返回的值是该客户端产生对影响AUTO_INCREMENT列的最新语句第一个 AUTO_INCREMENT值的。这个值不能被其它客户端影响,即使它们产生它们自己的 AUTO_INCREMENT值。这个行为保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁或处理。&
&&&&每次mysql_query操作在mysql服务器上可以理解为一次“原子”操作,&写操作常常需要锁表的, 是mysql应用服务器锁表不是我们的应用程序锁表。
&&&&值得注意的是,如果你一次插入了多条记录,这个函数返回的是第一个记录的ID值。
&&&&因为LAST_INSERT_ID是基于Connection的,只要每个线程都使用独立的Connection对象,LAST_INSERT_ID函数将返回该Connection对AUTO_INCREMENT列最新的insert or update*作生成的第一个record的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁。使用单INSERT语句插入多条记录,& LAST_INSERT_ID返回一个列表。
&&&&LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变。
方法二是使用max(id)
使用last_insert_id是基础连接的,如果换一个窗口的时候调用则会一直返回10
如果不是频繁的插入我们也可以使用这种方法来获取返回的id值
select max(id)
这个方法的缺点是不适合高并发。如果同时插入的时候返回的值可能不准确。
方法三是创建一个存储过程,在存储过程中调用先插入再获取最大值的操作
DELIMITER $$
DROP PROCEDURE IF EXISTS `test` $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `test`(in name varchar(100),out oid int)
insert into user(loginname) values(name);
select max(id)
DELIMITER ;
call test('gg',@id);
方法四使用@@identity
select @@IDENTITY &&&&@@identity是表示的是最近一次向具有identity属性(即自增列)的表插入数据时对应的自增列的值,是系统定义的全局变量。一般系统定义的全局变量都是以@@开头,用户自定义变量以@开头。比如有个表A,它的自增列是id,当向A表插入一行数据后,如果插入数据后自增列的值自动增加至101,则通过select @@identity得到的值就是101。使用@@identity的前提是在进行insert操作后,执行select @@identity的时候连接没有关闭,否则得到的将是NULL值。
方法五是使用getGeneratedKeys()
Connection conn = ;
Serializable ret =
PreparedStatement state = .;
ResultSet rs=
state.executeUpdate();
rs = state.getGeneratedKeys();
if (rs.next()) {
ret = (Serializable) rs.getObject(1);
} catch (SQLException e) {
总结一下,在mysql中做完插入之后获取id在高并发的时候是很容易出错的。另外last_insert_id虽然是基于session的但是不知道为什么没有测试成功。
其实在ibtias框架里使用selectkey这个节点,并设置insert返回值的类型为integer,就可以返回这个id值。
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读在存储过程中如何使用另一个存储过程返回的结果集
在存储过程中如何使用另一个存储过程返回的结果集
与这个问题具有相同性质的其他描述还包括:
如何在存储过程中检索动态SQL语句的执行结果?
如何实现类似SELECT * FROM (EXEC procedure_name @parameters_var) AS datasource WHERE ... 的功能?
procedure_name是一个存储过程的名字,@parameters_var是过程参数
如何将一个存储过程的执行结果记录集传递给另一个存储过程?
存储过程中如何根据另一个存储过程的执行结果选择执行流程?
存储过程中如何根据动态SQL语句的查询结果更改执行流程?
一个存储过程A使用另一个存储过程B的名字(或一段SQL语句或一个不确定的表名,字段名)作为参数,如何在不改动存储过程B的情况下,对存储过程B的执行结果记录集进行过滤/更改,再将过滤/更改后的结果集返回给存储过程A的调用者?
上面这些问题都有一个共同点,那就是都希望对存储过程(或动态SQL语句)的执行结果进行再处理,但是标准的SQL语句只能处理数据表,而一个存储过程(或动态SQL语句)的执行结果虽然是记录集,但它们本身不能当做数据表来处理。这样就大大限制了存储过程(或动态SQL语句)的应用范围,它们只能作为将记录集返回给应用程序前的最后一个处理层。如果我们可以像使用普通的数据表那样使用存储过程(或动态SQL语句)该有多好。
这个问题我以前的解决方法是使用OPENQUERY()或OPENDATASOURCE(),但OPENQUERY()不仅要求建立一个链接服务器,而且执行性能也让人无法满意。OPENDATASOURCE()则要求提供连接字符串,这对后期的维护也是一个很大的麻烦。
今天使用SQL Server联机丛书时无意中发现了一条SQL语句,竟然非常方便的解决了这个问题。这个语句就是INSERT语句。
INSERT语句在帮助中的定义是这样的:
INSERT [ INTO]
{ table_name WITH ( & table_hint_limited & [ ...n ] )
| view_name
| rowset_function_limited
{ [ ( column_list ) ]
( { DEFAULT | NULL | expression } [ ,...n] )
| derived_table
| execute_statement
| DEFAULT VALUES
其中execute_statement的解释是&任何有效的 EXECUTE 语句,它使用 SELECT 或 READTEXT 语句返回数据。&。通常我们放在这个位置的就是一段SELECT语句。但帮助既然说&任何有效的 EXECUTE 语句&,那么&EXEC procedure_name&也应该可以罗?想到这一点,马上决定动手验证一下。验证结果证实没问题。即下面这样的语句
INSERT INTO table_name EXEC procedure_name @parameters_var
确实可以正常工作。有了这个基础,我们也就有了解决本文开头那些问题的方法。
基本思路是先创建一个临时表,通过INSERT ... EXEC ...语句将存储过程的返回结果保存到临时表中,接下来就可以像处理普通数据表那样对待这个临时表了。对于动态SQL语句,可以通过dbo.sp_executesql存储过程执行,或者直接作为EXEC的参数执行。具体的编写要求可以参考SQL Server联机丛书。这里只特别说明一下,临时表的表结构与存储过程(或动态SQL语句)返回的记录集的表结构兼容即可,不要求完全相同。如果直接通过EXEC执行动态SQL语句,SQL语句有4K的长度限制。
最后给出两种最常见的处理流程:
1。创建一个临时表#tmp,表结构与目标存储过程procedure_name的返回结果集兼容(兼容即可,不必相同)。
CREATE TABLE #tmp(
[columns_list]
2。执行存储过程并将存储过程的返回结果集插入临时表。
INSERT INTO #tmp EXEC procedure_name @parameters_var
3。现在可以使用(过滤,更改或检索)#tmp了。^_^
IF EXISTS(SELECT * FROM #tmp)
--执行分支1
END ELSE BEGIN
--执行分支2
4。别忘了最后清除临时表。
DROP TABLE #tmp
对于动态SQL语句,只要将第二步改为
INSERT INTO #tmp EXEC dbo.sp_executesql @querystring_var随笔 - 148&
文章 - 69&
trackbacks - 0
29301234567891012131415161819202122232425262728293031123456789
我的其它Blog:
随笔分类(147)
随笔档案(148)
文章分类(28)
文章档案(28)
喜欢的Blog
阅读排行榜
评论排行榜
数据库实际应用中,我们往往需要得到刚刚插入 的标志值来往相关表中写入数据。但我们平常得到的真的是我们需要的那个值么?有时我们会使用 SELECT &#64;&#64;Identity 来获得我们刚刚插入的值,比如下面的代码
use&tempdbif&exists&(select&*&from&sys.objects&where&object_id&=&object_id(N'[test1]')&and&type&in&(N'u'))drop&table&[test1]gocreate&table&test1(id&int&identity(1,1),content&nvarchar(100))insert&into&test1&(content)&values&('solorez')select&&#64;&#64;identity
乐观情况下,这样做是没问题的,但如果我们如果先运行下面的代码二创建一个触发器、再运行代码三:
create&table&test2(id&int&identity(100,1),content&nvarchar(100))create&trigger&tri_test1_identitytest_Ion&test1&after&insertasbegininsert&into&test2&select&content&from&insertedend
insert&into&test1&(content)&values&('solorez2')select&&#64;&#64;identity
&我们可以看到,此时得到的标识值已经是100多了,很明显,这是表test2的生成的标识值,已经不是我们想要的 了。我们可以看看&#64;&#64;identity的定义:Identity原来,&#64;&#64;identity返回的是当前事务最后插入的标识值。这 时我们或许会用下面的方法:
insert&into&test1&(content)&values&('solorez3')SELECT&IDENT_CURRENT('test1')
看来结果还比较正确,但如果我们在多次运行代码四的同时运行下面的代码五:
insert&into&test1&(content)&values&('solorez3')waitfor&delay&'<span style="color: #ff:20'SELECT&IDENT_CURRENT('test1')
&结果又 不是我们想要的了!再看看IDENT_CURRENT(Tablename) 的定义:IDENT_CURRENT(Tablename)是 返回指定表的最后标识值。
到这里,是该亮出答案的时候了,我们可以使用下面的代码:
insert&into&test1&(content)&values&('solorez3')SELECT&scope_identity()
这时,我们无论是添加触发器还是运行并行插入,得到的始终是当前事务的标识值。
scope_identity()的定义:scope_identity()&
Table表中有一字段为自增长列(也称标识列,即Identity Increment),那么如何获取该列的下一行标识值呢,或刚插入的标识值?&
经过一番探索,下面的代码有效:
--获取刚插入的标识值
SELECT IDENT_CURRENT('TableName') from TableName&
--获取下一行的标识值
declare &#64;NextIdentity int
SELECT &#64;NextIdentity = IDENT_CURRENT('TableName') + IDENT_INCR('TableName') from TableName
if (&#64;NextIdentity is null)
&& set &#64;NextIdentity = IDENT_SEED('TableName')& --如查询表为空,则取标识列起始值
将TableName换成所需计算的表名即可。
摘要:本文向您介绍如何在SQL Server中准确的获得标识值,在SQL Server中,有三种不同的函数可以帮助我们达到目的。
SQL Server有三种不同的函数可以用来获得含有标识列的表里最后生成的标识值:
&#64;&#64;IDENTITY&& SCOPE_IDENTITY()&& IDENT_CURRENT('数据表名') 以上三个函数虽然都可以返回数据库引擎最后生成插入标识列的值,但是根据插入行的来源(例如:存储过程或触发器)以及插入该行的连接不同,这三个函数在功 能上也有所不同。
&#64;&#64;IDENTITY函数可以返回所有范围内当前连接插入最后所生成的标识值(包括任何调用的存储过程和触发器)。这个函数不止可以适用于表。函数 返回的值是最后表插入行生成的标识值。
SCOPE_IDENTITY()函数跟上一个函数几乎是一摸一样的,不同的地方:即前者返回的值只限于当前范围(即执行中的存储过程)。
最后是IDENT_CURRENT函数,它可以用于所有范围和所有连接,获得最后生成的表标识值。跟前面两个函数不同的是,这个函数只用于表,并且 使用[数据表名]作为一个参数。
我们可以举实例来演示上述函数是如何运作的。
首先,我们创建两个简单的例表:一个代表客户表,一个代表审计表。创建审计表的目的是为了跟踪数据库里插入和删除信息的所有记录。
以下是引用片段:
CREATE TABLE dbo.customer&& (customerid INT IDENTITY(1,1) PRIMARY KEY)&& GO&& CREATE TABLE dbo.auditlog&& (auditlogid INT IDENTITY(1,1) PRIMARY KEY,&& customerid INT, action CHAR(1),&& changedate datetime DEFAULT GETDATE())&& GO 然后,我们还要创建一个存储过程和一个辅助 触发器,这个存储过程将在数据库表里插入新的客户行,并返回生成的标识值,而触发器则会向审计表插入行:
以下是引用片段:
CREATE PROCEDURE dbo.p_InsertCustomer &#64;customerid INT output&& AS&& SET nocount ON&& INSERT INTO dbo.customer DEFAULT VALUES& SELECT &#64;customerid = &#64;&#64;identity&& GO&&
CREATE TRIGGER dbo.tr_customer_log ON dbo.customer&& FOR INSERT, DELETE&& AS&& IF EXISTS (SELECT 'x' FROM inserted)&& INSERT INTO dbo.auditlog (customerid, action)&& SELECT customerid, 'I'&& FROM inserted ELSE&& IF EXISTS (SELECT 'x' FROM deleted)&& INSERT INTO dbo.auditlog (customerid, action)&& SELECT customerid, 'D'&& FROM deleted&& GO 现在我们可以执行程序,创建客户表的第一行了,以下是引用片段:
DECLARE &#64;customerid INT&& EXEC dbo.p_InsertCustomer &#64;customerid output&& SELECT &#64;customerid AS customerid
执行后返回了我们需要的第一个客户的值,并记录了插入审计表的条目。到目前为止,数据显示没有任何问题。
假设由于先前沟通出现了偏差,一个客户服务代表现在需要从数据库里删除掉这个新增的客户。我们现在就来把新插入的客户行删除掉:
以下是引用片段:
DELETE FROM dbo.customer WHERE customerid = 1 现在,客户工作表为空表,而审计工作表里则有两行&#8212;&#8212;第一行是记录第一次插入行,第二行是记录删除客户记录。
现在我们再往数据库里增加第二个客户信息并检测一下获得的标识值:
以下是引用片段:
DECLARE &#64;customerid INT&& EXEC dbo.p_InsertCustomer &#64;customerid output&& SELECT &#64;customerid AS customerid
哇!看看出现了什么情况!如果我们现在再看客户工作表,就会发现虽然创建了客户2,但是我们的程序返回的标识值为3!到底出了什么问题呢?回想一 下,前面讲过&#64;&#64;IDENTITY函数的作用范围,它会返回主程序调用的任何存储过程或触动任何触发器最后生成的标识值,取决于哪一个在函数被调用前最后 生成标识值。在我们的例子里,初始范围是p_InsertCustomer,然后是触发器用来记录插入条目的tr_customer_log。因此我们返 回获得的标识值是审计工作表里触发器插入生成的标识值,而不是我们想要的客户工作表里的生成的标识值。
在SQL Server 2000之前的版本,&#64;&#64;IDENTITY函数是获得标识值的唯一方法。由于会出现这样的存储过程/触发器问题,SQL Server开发团队在SQL Server 2000中引入了 SCOPE_IDENTITY()和IDENT_CURRENT这两个函数来解决这个问题。所以在旧的SQL Server版本里,要解决这个问题比较麻烦。如果是SQL Server6.5版本,我建议可以去掉标识列,然后创建一个可以包含下一个需要使用的值的辅助表,可以达到标识列的作用效果。不过这个办法也不是什么高 明的办法。
现在我们来修改一下存储过程来使用SCOPE_IDENTITY()函数,并重新执行程序来添加第三个客户条目:
以下是引用片段:
ALTER PROCEDURE dbo.p_InsertCustomer &#64;customerid INT output&& AS&& SET nocount ON&& INSERT INTO dbo.customer DEFAULT VALUES&& SELECT &#64;customerid = SCOPE_IDENTITY()&& GO&& DECLARE &#64;customerid INT&& EXEC dbo.p_InsertCustomer &#64;customerid output&& SELECT &#64;customerid AS customerid 我们返回的标识值还是3,不过这次我们获得的标识值是正确的,因为我们添加了第三个客户条 目。如果我们检查一下审计工作表,就会发现里面已经有第四个条目记录新插入的客户记录。由于函数SCOPE_IDENTITY()只作用于当前范围,只返 回当前执行程序的值,这样就避免了发生刚才那样的问题。
前面讲过,函数&#64;&#64;IDENTITY和函数SCOPE_IDENTITY()不止用于表,不像函数IDENT_CURRENT那样可以用表作为参 数。使用&#64;&#64;IDENTITY和SCOPE_IDENTITY()这两个函数的话在设置代码时需要加倍小心,才能够从所需要的表里获得正确的标识值。从表 面上来看,放弃这两个函数,只使用函数IDENT_CURRENT并指定表是更安全的办法。这样可以避免出现获得错误标识值的情况,对吧?记得先前说过函 数IDENT_CURRENT不仅会跨范围,而且它还会跨连接。也就是说,使用这个函数生成的值不仅仅限于你的连接所执行的程序,它的涵盖范围还包括整个 数据库所有的连接。因此,即使是在规模较小的OLTP环境里,它也会出现不能准确返回所需值的问题。这样就可能发生类似前面&#64;&#64;IDENTITY函数/触 发器的数据损坏问题。
我的建议是函数SCOPE_IDENTITY()是三个函数里最安全的函数,应该设置为默认函数。使用这个函数,你可以放心地添加触发器和次存储过 程,无需担心意外损坏数据。而另外两个函数可以保留应付特殊的情况,当遇到需要使用这两个函数的特殊情况时,建议记录它们的使用情况并进行测试。
Sql Server 判断表是存在标识列
If Exists(Select * from SysColumns Where ID=OBJECT_ID(N'TEST1') And COLUMNPROPERTY(ID,Name,'IsIdentity')=1)Print N'有自增列'ElsePrint N'没有自增列'
Sql Server 显示当前数据库包含自增列的表Select b.name,a.* from SysColumns a,sysobjects b Where a.id=b.id and COLUMNPROPERTY(a.ID,a.Name,'IsIdentity')=1
SQL SERVER自增长字段复位方法:
SQLSERVER 复位:
Truncate table Ashare_CJHBDbcc checkident (Ashare_CJHB,RESEED,0)
获取最后sql影响记录的最后ID,慎用&#64;&#64;Identity 我们常用的获sql影响的最后记录id常用的是&#64;&#64;identity,但有些情况下会有问题,其实sql一共提供了3个不同的方法
SELECT SCOPE_IDENTITY()
select IDENT_CURRENT(TableName)
select &#64;&#64;IDENTITY
IDENT_CURRENT 类似于 SQL Server 2000 标识函数 SCOPE_IDENTITY 和 &#64;&#64;IDENTITY。这三个函数都返回最后生成的标识值。但是,上述每个函数中定义的&#8220;最后&#8221;的作用域和会话有所不同。
IDENT_CURRENT 返回为某个会话和用域中的指定表生成的最新标识值。
&#64;&#64;IDENTITY 返回为跨所有作用域的当前会话中的某个表生成的最新标识值。
SCOPE_IDENTITY 返回为当前会话和当前作用域中的某个表生成的最新标识值。
在空表中调用 IDENT_CURRENT 函数时,此函数将返回 NULL。
如果语句和事务失败,它们会更改表的当前标识,从而使标识列中的值出现不连贯现象。即使未提交试图向表中插入值的事务,也永远无法回滚标识值。例 如,如果因 IGNORE_DUP_KEY 冲突而导致 INSERT 语句失败,表的当前标识值仍然会增加。
&#64;&#64;IDENTITY 表示插入后新的表示种子值,例子如下:假如已经存在表job,向表插入一条数据,INSERT INTO jobs (job_desc,min_lvl,max_lvl)VALUES ('Accountant',12,125)SELECT &#64;&#64;IDENTITY AS 'Identity'//获得表识值
阅读(1682)相关文章推荐:
C select @@IDENTITY;
--第一步成功
use northwind
select orderid, customerid, orderdate
into oldorders
from orders
where orderdate
回复 (4) 浏览 (4296)
其他文章推荐
ITPUB官方微博:
EXECUTEIMMEDIATE'insertintoygl_tmp0706(s1)values('sdf')';这个字符串一直提示报错,请问下在存储过程中的动态语句,要直接写字符要怎么写啊?...
回复 (18) 浏览 (361)
模拟行迁移:SQL&createtabletestrow(idchar(100),id2varchar2(4000),id3varchar2(4000))pctfree98pctused2;TablecreatedSQL&insertintotestrowvalues('1','2','3');1rowinsertedSQL&CommitcompleteSQL&@?/rdbms/admin/utlchain.sqlTablecreatedSQL&ANA ......
回复 (4) 浏览 (252)
本帖最后由默默叽叽于:52编辑先说正常的EXTRACText1SETENV(NLS_LANG=AMERICAN_AMERICA.UTF8)DBOPTIONSALLOWUNUSEDCOLUMNUSERIDggs,PASSWORDggsTRANLOGOPTIONS,BUFSIZE4096000FORMATASCII,NONAMES,DELIMITER'|',NOQUOTE,NOHDRFIELDS,NULLISSPACEEXTFILE/u01/as ......
回复 (1) 浏览 (171)
SQL&createtablecompany_holidays(daydate);SQL&insertintocompany_holidaysvalues(to_date('21-10-01','DD-MON-YY'));insertintocompany_holidaysvalues(to_date('21-10-01','DD-MON-YY'))*ERRORatline1:ORA-01843:notavalidmonth我要表示的是10月啊,哪错了?谢谢 ......
回复 (6) 浏览 (244)
今天做了测试在关联表中(就是有主外键的表)中对主表的insert操作会在子表上产生row-x(SS)锁,这是为什么呢?Oracle为什么会这样做呢?在主表的insert操作对子表有什么影响麽需要加在子表上加SS锁麽?...
回复 (1) 浏览 (362)
更多精彩内容尽在&《OracleRAC故障分析与处理》一&RAC环境RAC架构,2节点信息节点1SQL&showparameterinstanceNAME&&&&&&&&&&&&&& ......
回复 (4) 浏览 (53)
第一次有机会能完整的在服务器上安装EBSR12.1.1,&然后做升级测试,&赶紧记录下来先。&一,介质下载&&到/EPD/Search/handle_go网站下载OracleE-BusinessSuiteRelease12.1.1MediaPackforLinuxx86-64-bit ......
回复 (5) 浏览 (29)
一&集群环境下的一些特殊问题&1.1&并发控制在集群环境中,&关键数据通常是共享存放的,比如放在共享磁盘上。&而各个节点的对数据有相同的访问权限,&这时就必须有某种机制能够控制节点对数据的访问。&Oracle&R ......
回复 (6) 浏览 (158)
最近需要生产系统从10.2.0.5.升级到11.2.0.2.0做了不少的准备工作,硬是在周末自己搭了测试环境,照着自己准备的升级步骤练习了一番。除过基本的检查,从Metalink上下载了最新的psu,和公司的资深dba确认后,提供了给了客户。这样数据库就算是升级到11.2.0.2.10主要有以 ......
回复 (3) 浏览 (27)
Rcoverdatabaseusingbackupcontrolfileafterdatafileaddedintodatabase&&该篇文章再现了使用备份控制文件恢复数据库,但是在控制文件备份之后向数据库里面添加了数据文件(没有开启控制文件自动备份),即改变了数据库的物理结构,导致物理结构和控制文件 ......
回复 (3) 浏览 (19)
文章推荐:
盛拓传媒:
友情链接:
特别鸣谢:
北京皓辰网域网络信息技术有限公司. 版权所有
北京市公安局海淀分局网监中心备案编号:
广播电视节目制作经营许可证:编号(京)字第1149号
ITPUB推荐文章解答你所有技术难题

我要回帖

更多关于 set identity insert 的文章

 

随机推荐