SQL Server 返回最后插入记录的自动编号ID

合集下载

sqlserver生成id的方法

sqlserver生成id的方法

SQL Server是一种流行的关系型数据库管理系统,它提供了许多不同的方法来生成唯一的ID。

在本篇文章中,我将探讨几种在SQL Server 中生成ID的方法,并分析它们各自的优缺点。

1. 自增字段自增字段是SQL Server中最常用的生成唯一ID的方法之一。

这种方法利用了数据库管理系统的自动增长功能,每当插入一条新的记录时,自增字段的值就会自动加1。

这种方法简单、直观,并且保证了唯一性,因此在许多情况下都是非常合适的选择。

但是,自增字段也存在一些局限性。

它只能应用在单表中,并且只能有一个自增字段。

一旦插入的记录被删除,相应的ID就会永久丢失,导致ID的不连续性。

另外,如果需要在插入记录之前就获取新记录的ID,自增字段也无法满足这一需求。

2. GUID全局唯一标识符(GUID)是一种128位的二进制标识符,它能够在全球范围内保证唯一性。

在SQL Server中,可以使用NEWID()函数来生成一个新的GUID。

这种方法的优点是非常适合分布式系统和复制环境,因为它可以保证不同数据库中的记录的唯一性,并且不需要和其他数据库进行通信。

然而,GUID也存在一些缺点。

由于它的长度较长,因此不适合作为主键,并且会占用更多的存储空间。

由于其无序性,在某些情况下会导致性能问题。

另外,GUID对于人类用户来说是不可读的,因此在某些情况下可能不够直观。

3. 序列SQL Server 2012引入了序列(Sequence)对象,它提供了一种可复用的数字范围生成器。

使用序列,可以在每次需要生成新的ID时调用NEXT VALUE FOR语句,来获取一个新的序列值。

序列在保证唯一性的还具有一定的灵活性,比如可以指定增量、起始值和最大值等属性。

然而,序列也存在一些限制。

它只能应用在单表中,且每个表只能有一个序列。

序列并不是完全自动增长的,需要显式地调用NEXT VALUE FOR语句,这使得它不太适合与INSERT语句一起使用。

MS SQL Server

MS  SQL  Server

文 件 id x ap 功 能 是 显 示 1 n e.s 面 数 据 库 中 表 d w la 的 所 有 数 据 , 为 了 美 观 使 用 表 格 , 其 内 容 o no d
如下 :
<! 一 一 #i ncl ude il = 。o f e 。 p ̄q1 nc” 一 一 > .i <ht l hea m X d><m et a htp — equi : 。 t v 。 Co ent— nt
<% 0  ̄ T F r s ] FO e 1 e xt
许 多 朋 友 上 阿 冲 浪 时 是 否 曾 经 注 意 到 , 多 网 页 许
名 称 的 尾 部 出 现 过 . ( : ht : ap 如 t //I7 0 0 I p 2 . . / id x a p , 利 用 I 浏 览 器 杳 源 代 码 的 功 能 , 我 们 n e. s ) E
置 应 为

变 得 简 易 , 由此在 众 多 WE 数 据 库 中 , B

为 常 见 、 实 用 的 MS S S re QI evr为 例 ,看 一 看 AS P 的源代码 足如何 实现 动态 网负技术 的 。 2 表 的 结 构 厦 相 关 参 数 等 的 设 置 1
S o a V rh r 5 h wu me ac a 0 N t oe 【 cm a ) i l e I ae i 8 tt n me 5 0 0 】 8
Typ e” cont nt= 一 t t e ex /bt l e m ; har e gb231 st 2”X tte> il
维普资讯
第 3卷 第 1 期 20 年 3月 02
涛商蕈微案枝 衔 学 院 学轻
J nrm]o a l a m me c a l t c n c o l fSh h 1 Co r i lpo y e h i

Mybatis+Mysql插入数据库返回自增主键id值的三种方法

Mybatis+Mysql插入数据库返回自增主键id值的三种方法

Mybatis+Mysql插⼊数据库返回⾃增主键id值的三种⽅法⼀、场景:插⼊数据库的值需要⽴即得到返回的主键id进⾏下⼀步程序操作⼆、解决⽅法:第⼀种:使⽤通⽤mapper的插⼊⽅法Mapper.insertSelective(record);此⽅法:插⼊⼀条数据,只插⼊不为null的字段,不会影响有默认值的字段⽀持Oracle序列,UUID,类似Mysql的INDENTITY⾃动增长(⾃动回写)优先使⽤传⼊的参数值,参数值空时,才会使⽤序列、UUID,⾃动增长controller的实际应⽤:使⽤⽅法id会直接将映射到参数的实体上使⽤时直接使⽤参数的实体get获取值第⼆种:编写sql语句dao层⽅法:[java]1. /**2. * 插⼊数据库并返回主键id3. * @param batch4. * @return5. */6. Integer insertBatchReturnId(Batch batch);xml的sql语句写法记得加上useGeneratedKeys和keyProperty配置即可,前者是指设置是否使⽤jdbc的getGenereatedKeys⽅法获取主键并赋值到keyProperty 设置的属性中,后者即实体类主键字段(并且⼤⼩写要对应上)[html]1. <insert id="insertBatchReturnId" useGeneratedKeys="true" keyProperty="id" parameterType="org.uz.dxt.model.bankbase.Batch" >2.3. insert into t_batch (4. batchCode,5. bankCode,6. bizType,7. companyCode,8. wtEndDate,9. wtDate,10. contractId,11. totalCount,12. totalBase,13. handCode)14. values15. ( #{batchcode},16. #{bankcode},17. #{biztype},18. #{companycode},19. #{wtenddate},20. #{wtdate},21. #{contractid},22. #{totalcount},23. #{totalbase},24. #{handCode})25. </insert>controller的实际应⽤:使⽤⽅法id会直接将映射到参数的实体上使⽤时直接使⽤参数的实体get获取值[java]1. batchService.insertBatch(param);//实体2. idlist.add(param.getId());第三种:sql语句使⽤<selectKey>获取⾃增逐渐id[html]1. <insert id="add" parameterType="EStudent">2. // 下⾯是SQLServer获取最近⼀次插⼊记录的主键值的⽅式3. <selectKey resultType="_long" keyProperty="id" order="AFTER">4. select @@IDENTITY as id5. </selectKey>6. insert into TStudent(name, age) values(#{name}, #{age})7. </insert>使⽤⽤法同上这⾥推荐使⽤第⼀种和第⼆种中⽅法第三种⽅法对oracl额外的配置controller的实际应⽤:使⽤⽅法id会直接将映射到参数的实体上使⽤时直接使⽤参数的实体get获取值。

SqlServer触发器实现自动编号

SqlServer触发器实现自动编号

触发器做个实现数据插入表时自动编号的功能,详细出处参考:/article/31031.htm总结常用基本点如下:1、触发器有两种类型:数据定义语言触发器(DDL触发器)和数据操纵语言触发器(DML 触发器)。

DDL触发器:在用户对数据库执行数据定义(CREATE、ALTER、DROP或相似的语句)对数据库结构进行修改时激活而做出响应。

DML触发器:在用户对数据库执行数据操作时发生,触发器中的代码会被自动调用。

2、DML触发器分类:Insert触发器、Delete触发器、Update触发器、上面任意类型混合。

3、触发器创建语法:复制代码代码如下:CREATE TRIGGER <trigger name>ON <table or view>{{{FOR|AFTER} <[INSERT] [,] [UPDATE],[DELETE]>}|INSTEAN OF}AS<sql statement>4、触发器必须附加到表或视图上,触发器不能单独存在。

AFTER或FOR触发器不支持视图,INSTEAD OF支持表或视图。

5、INSERT触发器中,SQL Server 会创建一个插入行的副本,并把该副本插入到一个特殊表Insert表中,该表只在触发器作用域内存在。

6、DELETE触发器中,SQL Server 会创建一个删除行的副本,并把该副本插入到一个特殊表Delete表中,该表只在触发器作用域内存在。

7、UPDATE触发器中,SQL Server认为更新的记录是删除了现有的记录,插入更新后的新纪录,所以UPDA TE触发器中包含Insert和Delete两个特殊表,也是只存在触发器作用域内,这两个表的行数完全一样。

8、触发器尽可能简短,因为触发器和触发器内的语句被一同处理,即直到语句执行完成才算是触发器完成。

如果代码很长那触发器运行时间就会很长。

下面是个实现自动编号功能的例子:--有两张表,客户表和项目表,要求:新建项目时自动生成项目编号,每个不同的客户的项目的编号从1开始--项目编号格式为PJ+"-"+"客户编号"+"-"+"日期"+"-"+"流水号"--如项目编号:PJ-ABCD-120805-0001create table testAccount --创建测试客户表(tAccName nvarchar(100), --客户姓名tAccId nvarchar(32) --客户编号)create table testProject --创建测试项目表(tProName nvarchar(100), --项目名称tProId nvarchar(32), --项目编号tIdAcc nvarchar(100), --客户编号tProGuid nvarchar(64) --guid)gocreate trigger T_AutoNumberon testProjectafter insertasbegindeclare @one nvarchar(8), --编号第一部分,PJ@two nvarchar(32), --编号第二部分,客户编号@three nvarchar(8), --编号第三部分,日期@four int, --编号第四部分,流水号@guid nvarchar(64) --guidset @one='PJ'set @three= convert( varchar(8),GETDA TE(),112)--从Inserted副本表里获取当前插入数据的客户编码和guidselect @two=tIdAcc,@guid=tProGuid from Inserted--获取编号最后四位select @four=max(cast(right(tProId,4)as int))from testProjectwhere tIdAcc=@two--对每一个新客户的流水号都是从1开始,已存在客户为最大流水号加1if @four is nullset @four=0elseset @four=cast(@four as int)set @four=@four+1update testProject set tProId=@one+'-'+@two+'-'+@three+'-'+right('0000'+cast(@four as varchar),4) where tProGuid=@guidendgo--生成测试表数据insert into testAccount values ('小小鸭有限公司','XXYGS')insert into testAccount values ('丑小鸭有限公司','CXY')insert into testProject (tProName,tIdAcc,tProGuid)values ('小鸭成长项目','XXYGS',newid()) insert into testProject (tProName,tIdAcc,tProGuid)values ('小鸭学游泳项目','XXYGS',newid()) insert into testProject (tProName,tIdAcc,tProGuid)values ('丑小鸭成长项目','CXY',newid()) select * from testProjectdrop table testAccountdrop table testProject。

利用SQL语句自动生成序号的两种方式

利用SQL语句自动生成序号的两种方式

利用"SQL"语句自动生成序号的两种方式SQL Server2005数据库中利用SQL语句自动生成序号:1.首先,我们来介绍第一种方式:◆查询的SQL语句如下:◆运行的结果:2.最后,我们来介绍第二种方式:在我们利用这种方式生成自动序号时,Test_Table必须在数据库中不能存在,因为在执行这些SQL语句的时后自动会创建表。

以下为实现SQL server中按年月日生成日期型自增编码的sql脚本:/** 测试表*/CREATE TABLE [dbo].[CustomIDTest] ([ID] [int] NOT NULL ,[Code] [char] (8) NOT NULL)/**//** 功能:按 YYYYxxxx 格式生成目标年份的最大编码,数据类型为 CHAR(8)* 说明:特定表范围内有效* 未处理溢出情况(当表中某年值已达到YYYY9999)*/CREATE FUNCTION dbo.GenCustomCode(@Year INT)RETURNS CHAR(8)ASBEGINDECLARE@Code CHAR(8),@MinCodeInYear CHAR(8),@MaxCodeInYear CHAR(8)SELECT @MinCodeInYear = CONVERT(CHAR(4), @Year) + '0001', @MaxCodeInYear = CONVERT(CHAR(4), @Year) + '9999'SELECT @Code = MAX(Code) FROM CustomIDTest WHERE Code >= @MinCodeInYear AND Code <= @MaxCodeInYearIF @Code IS NOT NULL AND @Year = CONVERT(INT, SUBSTRING(@Code, 1, 4)) /**//*IF @Code = @MaxCodeInYear 溢出处理*/SET @Code = CONVERT(INT, @Code) + 1ELSESET @Code = @MinCodeInYearRETURN @CodeEND/**//** 功能:按 YYYYxxxx 格式生成目标年份的最大ID,数据类型为 INT* 说明:特定表范围内有效* 未处理溢出情况(当表中某年值已达到YYYY9999)*/CREATE FUNCTION dbo.GenCustomID(@Year INT)RETURNS INTASBEGINDECLARE@ID INT,@MinIDInYear INT,@MaxIDInYear INTSELECT @MinIDInYear = @Year*10000 + 1, @MaxIDInYear = @Year*10000 + 9999SELECT @ID = MAX(ID) FROM CustomIDTest WHERE ID >= @MinIDInYear AND ID <= @MaxIDInYearIF @ID IS NOT NULL AND @Year = @ID/10000/**//*IF @ID = @MaxIDInYear 溢出处理*/SET @ID = @ID + 1ELSESET @ID = @MinIDInYearRETURN @IDEND-- 测试-- 自定义年份内自增INSERT INTO CustomIDTest([ID], [Code])SELECT dbo.GenCustomID(DatePart(YY, DATEADD(YY, -1, GetDate()))), dbo.GenCustomCode(DatePart(YY, DATEADD(YY, -1, GetDate())))UNIONSELECT dbo.GenCustomID(DatePart(YY, GetDate())), dbo.GenCustomCode(DatePart(YY, GetDate()))UNIONSELECT dbo.GenCustomID(DatePart(YY, DATEADD(YY, 1, GetDate()))), dbo.GenCustomCode(DatePart(YY, DATEADD(YY, 1, GetDate())))SELECT * FROM CustomIDTest结果ID Code----------- --------20060001 2006000120060002 2006000220060003 2006000320060004 2006000420070001 2007000120070002 2007000220070003 2007000320070004 2007000420080001 2008000120080002 2008000220080003 2008000320080004 20080004说明:1、对于此示例,一年内最大增量只有,9999,需要考虑溢出如何处理,此版本未处理2、因此,根据实际需求,我们可以选择以“天”为编码前缀,并且扩大自增部分长度,避免溢出,3、当然此时得考虑,使用 INT 型长度是否足够4、此版本自定义函数,使用传入年份参数5、若欲始终使用当前系统日期,而不显示指定年份,则需要建立一视图来获取当前日期(因SQLServer中标量函数,不能使用 GetDate() 这样的非标量函数)详细讲解有关获取当月天数的实用技巧获取当月天数的实用技巧:以下是引用片段:分析如下:以下是引用片段:以下是引用片段:5. SYBASESELECT TOP N * FROM TABLE16. mysql:select * from table_name limit N为什么SQL不许在视图定义ORDER BY子句发布时间:2007.08.03 05:01来源:赛迪网作者:luoyingshu 问:为什么SQL Server不允许在视图定义使用ORDER BY子句?答: SQL Server之所以不允许在视图定义中使用ORDER BY子句是为了遵守ANSI SQL-92标准。

sqlserver自动生成日期加数字的序列号

sqlserver自动生成日期加数字的序列号

sqlserver自动生成日期加数字的序列号需求:需要生成下面地序列号,前半部分是yyyymmdd格式地年月日时间数字,后半部分则是每天都从1顺序增长地数字,位数要固定,中间不足地补0.在sql server 2000数据库中测试后通过如下代码,功能实现如下:use mastergoif exists(select * from dbo.sysdatabases where name='my_test_database')drop database [my_test_database]gocreate database [my_test_database]gouse [my_test_database]gocreate table [my_table] ([my_id] varchar(16))go--存储过程开始create procedure get_new_id@new_id varchar(16) outputasbegindeclare @date datetimedeclare @yyyy varchar(4)declare @mm varchar(2)declare @dd varchar(2)--保存取的地当前时间set @date = getdate()set @yyyy = datepart(yyyy, @date)set @mm = datepart(mm, @date)set @dd = datepart(dd, @date)--位数不够地前面补0set @yyyy = replicate('0', 4 - len(@yyyy)) + @yyyyset @mm = replicate('0', 2 - len(@mm)) + @mmset @dd = replicate('0', 2 - len(@dd)) + @dd--取出表中当前日期地已有地最大idset @new_id = nullselect top 1 @new_id = [my_id] from [my_table] where [my_id] like @yyyy+@mm+@dd+'%' order by [my_id] desc --如果未取出来if @new_id is null--说明还没有当前日期地编号,则直接从1开始编号set @new_id = (@yyyy+@mm+@dd+'00000001')--如果取出来了elsebegindeclare @num varchar(8)--取出最大地编号加上1set @num = convert(varchar, (convert(int, right(@new_id, 8)) + 1)) --因为经过类型转换,丢失了高位地0,需要补上set @num = replicate('0', 8 - len(@num)) + @num--最后返回日期加编号set @new_id = @yyyy+@mm+@dd + @numendendgo--执行20次调用及插入数据测试declare @n intset @n = 0while @n < 20begindeclare @new_id varchar(16)execute get_new_id @new_id outputinsert into [my_table] ([my_id]) values (@new_id) set @n = @n + 1endselect * from [my_table]go--输出结果/**//*my_id----------------20060927000000012006092700000002200609270000000320060927000000042006092700000005200609270000000620060927000000072006092700000008200609270000000920060927000000102006092700000011200609270000001220060927000000132006092700000014200609270000001520060927000000162006092700000017200609270000001820060927000000192006092700000020*/注释:原来yyyymmdd格式地日期直接这样取即可:select convert(char(8), getdate(), 112)--输出结果:/**//*--------20060927*/:更多信息请查看IT技术专栏。

SQL Server获取插入数据的自增长字段的值

SQL Server获取插入数据的自增长字段的值

在Sql Server中插入一条数据,想立即获取它标识值,可以用以下
三中方法:
1.SCOPE_IDENTITY - scope_identity()
返回当前会话和当前作用域中的任何表最后生成的标识值。

一个作用域就是一个模块——存储过程、触发器、函数或批处理。

因此,如果两个语句处于同一个存储过程、函数或批处理中,则它们位于相同的作用域中。

2.IDENT_CURRENT - ident_current('表名')
返回任何会话和任何作用域中的指定表最后生成的标识值。

这个函数需要一个以表名为值的变量,也就是说虽然不受会话和作用域的限制,却会受到表的限制。

3.@@IDENTITY - 全局变量
返回为当前会话的所有作用域中的任何表最后生成的标识值。

一直以来都是使用@@identity来获得最后一个插入到表的记录的identity值,最近发现这种方法在某种情况是不可靠的,先来看看
两个概念
作用域:在SQL SERVER作用域就是一个模块-存储过程,触发器,
函数或批处理
会话:一个用户连接产生的所有上下文信息
相同点:都是返回最后插入的标识值
不同点:
@@identity:返回当前会话最后一个标识值,不限于特定的作用域;ident_current('tablename'):返回任何会话,任何作用域中的指定表中生成的最后一个标识值;
scope_identity:返回当前会话当前作用域任何表生成的最后一个标识值。

sql执行insert插入一条记录同时获取刚插入的id

sql执行insert插入一条记录同时获取刚插入的id

sql执⾏insert插⼊⼀条记录同时获取刚插⼊的id有两种⽅式可以获得刚新插⼊的id ①从inserted临时表中查询 ②使⽤全局变量@@identity 查询1、使⽤ output 关键字输出inserted临时表的 id在执⾏insert之后,inserted 为已插⼊的临时表,可以从临时表得到刚刚插⼊该表的 id 了。

insert into t_student(name,studentno,sex,age)output inserted.id values('张连康','101001','男',22)2、使⽤SQL的变量或全局参数select@@IDENTITY--返回为当前会话的所有作⽤域中的任何表最后⽣成的标识值。

select IDENT_CURRENT('table_name') --返回为任何会话和任何作⽤域中的特定表最后⽣成的标识值,它不受作⽤域和会话的限制,⽽受限于所指定的表select SCOPE_IDENTITY() --返回为当前会话和当前作⽤域中的任何表最后⽣成的标识值。

最常使⽤的应该是 @@identity ,但是它是全局下的新插⼊的id,也就是如果有多线程的话,那么获取的不⼀定是想要的结果。

insert into t_student(studentNo,name,sex,age) values('150********','zlk','man',22)select @@IDENTITY 我们建⽴⼀个触发器来测试这种⽅式得到的id,触发器的效果为:当向 t_student 表中插⼊⼀条记录时,同时也向 t_class 表中插⼊⼀条记录。

create trigger trig_studentClasson t_student for insertasinsert into t_class (classNo,className)values('001','计算机科学与技术')这三个的更多的使⽤说明,可以查看SQL联机帮助⼿册,⾥⾯有详细的说明。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

SQL Server 返回最后插入记录的自动编号ID
最近在开发项目的过程中遇到这么一个问题,就是在插入一条记录的后立即获取其在数据库中自增的ID,以便处理相关联的数据,怎么做?在sql server 2000中可以这样做,有几种方式。

详细请看下面的讲解与对比。

一、要获取此ID,最简单的方法就是:(以下举一简单实用的例子)
--创建数据库和表
create database MyDataBase
use MyDataBase
create table mytable
(
id int identity(1,1),
name varchar(20)
)
--执行这个SQL,就能查出来刚插入记录对应的自增列的值
insert into mytable values('李四')
select @@identity
二、三种方式的比较
SQL Server 2000中,有三个比较类似的功能:他们分别是:SCOPE_IDENTITY、IDENT_CURRENT 和@@IDENTITY,它们都返回插入到IDENTITY 列中的值。

IDENT_CURRENT 返回为任何会话和任何作用域中的特定表最后生成的标识值。

IDENT_CURRENT 不受作用域和会话的限制,而受限于指定的表。

IDENT_CURRENT 返回为任何会话和作用域中的特定表所生成的值。

@@IDENTITY 返回为当前会话的所有作用域中的任何表最后生成的标识值。

SCOPE_IDENTITY 返回为当前会话和当前作用域中的任何表最后生成的标识值SCOPE_IDENTITY 和@@IDENTITY 返回在当前会话中的任何表内所生成的最后一个标识值。

但是,SCOPE_IDENTITY 只返回插入到当前作用域中的值;@@IDENTITY 不受限于特定的作用域。

例如,有两个表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多行时就会并发冲突.在P4
2.8C,512M DDR上,才6000多行时就并发冲突.
2.SCOPE_IDENTITY()是绝对可靠的,可以用在存储过程中,连触发器也不用建,没并发冲突
SELECT IDENT_CURRENT('TableName') --返回指定表中生成的最后一个标示

SELECT IDENT_INCR('TableName')--返回指定表的标示字段增量值
SELECT IDENT_SEED('TableName')--返回指定表的标示字段种子值
返回最后插入记录的自动编号
SELECT IDENT_CURRENT('TableName')
返回下一个自动编号:
SELECT IDENT_CURRENT('TableName') + (SELECT IDENT_INCR('Table Name'))
SELECT @@IDENTITY --返回当前会话所有表中生成的最后一个标示值
以上是针对sql server 2000的情况,但是诸如my sql或oracle中如何实现呢?怎么处理呢?本人也在摸索中。

如有朋友知道此处理方式,别忘了告之,一同分享!。

相关文档
最新文档