使用IDENTITY列属性和Sequence对象
使用IDENTITY列属性
1. 建立表 Sales.MyOrders
USE TSQL2012; IF OBJECT_ID(N'Sales.MyOrders', N'U') IS NOT NULL DROP TABLE Sales.MyOrders; GO CREATE TABLE Sales.MyOrders ( orderid INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_MyOrders_orderid PRIMARY KEY, custid INT NOT NULL CONSTRAINT CHK_MyOrders_custid CHECK(custid > 0), empid INT NOT NULL CONSTRAINT CHK_MyOrders_empid CHECK(empid > 0), orderdate DATE NOT NULL );
2. 插入一些记录
INSERT INTO Sales.MyOrders ( custid, empid, orderdate ) VALUES ( 1, 2, '20120620' ), ( 1, 3, '20120620' ), ( 2, 2, '20120620' );
3. IDENTITY 相关函数
SELECT SCOPE_IDENTITY() AS SCOPE_IDENTITY, /*返回插入到同一作用域中的标识列内的最后一个标识值。 一个范围是一个模块:存储过程、触发器、函数或批处理。 因此,如果两个语句处于同一个存储过程、函数或批处理中,则它们位于相同的作用域中。 */ @@IDENTITY AS [@@IDENTITY], --与上面一样返回同一作用域内的最后一个标示符,但是不限作用域。 IDENT_CURRENT('Sales.MyOrders') AS IDENT_CURRENT; --返回为指定的表或视图生成的最后一个标识值。
4. 如果Truncate 表,该表的IDENTITY的值就会重置,仅仅删除记录不会。
TRUNCATE TABLE Sales.MyOrders; SELECT IDENT_CURRENT('Sales.MyOrders') AS [IDENT_CURRENT];
5. 使用DBCC CHECKINDENT 续种
DBCC CHECKIDENT('Sales.MyOrders', RESEED, 4); INSERT INTO Sales.MyOrders(custid, empid, orderdate) VALUES(2, 2, '20120620'); SELECT * FROM Sales.MyOrders;
使用Sequence 对象
SQL Server 2012起引入了新的数据库对象 sequence,它不像IDENTITY 列属性有那么多限制(比如 IDENTITY 属性只能应用在某个表的某一列。 有时候你希望多个表的key没有冲突,但是IDENTITY无法跨表操作。你希望先生成一个值再使用,也不行。 你无法更新IDENTITY列。 IDENTITY 无法循环使用。 Truncate 会重置 IDENTITY值 )
1. 创建sequence
-- create sequence IF OBJECT_ID(N'Sales.SeqOrderIDs', N'SO') IS NOT NULL DROP SEQUENCE Sales.SeqOrderIDs; --部分参数 --INCREMENT BY 增量值,默认为1 --MINVALUE 最小值,默认为数据类型的最小值,比如INT的最小值为 -2147483648 --MAXVALUE 最大值,默认值为数据类型的最大值 --CYCLE|NO CYCLE 是否循环,默认为不循环 --START WITH ,设置一个起始值,默认起始值是升序序列对象的最小值和降序序列对象的最大值。 CREATE SEQUENCE Sales.SeqOrderIDs AS INT MINVALUE 1 CYCLE;
2. 查询系统中的sequence
SELECT TYPE_NAME(system_type_id) AS type , start_value , minimum_value , current_value , increment , is_cycling FROM sys.sequences WHERE object_id = OBJECT_ID(N'Sales.SeqOrderIDs', N'SO');
3. 获取一个新值
-- request a new value; SELECT NEXT VALUE FOR Sales.SeqOrderIDs;
4. 序列的所有属性都可以通过ALTER SEQUENCE命令修改。比如更改当前值
ALTER SEQUENCE Sales.SeqOrderIDs RESTART WITH 1;
5. 实际运用
a) 创建Sales.MyOrders 表并插入数据
-- recreate Sales.MyOrders table IF OBJECT_ID(N'Sales.MyOrders', N'U') IS NOT NULL DROP TABLE Sales.MyOrders; GO CREATE TABLE Sales.MyOrders ( orderid INT NOT NULL CONSTRAINT PK_MyOrders_orderid PRIMARY KEY, custid INT NOT NULL CONSTRAINT CHK_MyOrders_custid CHECK(custid > 0), empid INT NOT NULL CONSTRAINT CHK_MyOrders_empid CHECK(empid > 0), orderdate DATE NOT NULL ); -- use in INSERT VALUES INSERT INTO Sales.MyOrders(orderid, custid, empid, orderdate) VALUES (NEXT VALUE FOR Sales.SeqOrderIDs, 1, 2, '20120620'), (NEXT VALUE FOR Sales.SeqOrderIDs, 1, 3, '20120620'), (NEXT VALUE FOR Sales.SeqOrderIDs, 2, 2, '20120620'); -- use in INSERT SELECT INSERT INTO Sales.MyOrders(orderid, custid, empid, orderdate) SELECT NEXT VALUE FOR Sales.SeqOrderIDs OVER(ORDER BY orderid), custid, empid, orderdate FROM Sales.Orders WHERE custid = 1;
b) 直接把sequence设为default约束
ALTER TABLE Sales.MyOrders ADD CONSTRAINT DFT_MyOrders_orderid DEFAULT(NEXT VALUE FOR Sales.SeqOrderIDs) FOR orderid;
测试
INSERT INTO Sales.MyOrders(custid, empid, orderdate) SELECT custid, empid, orderdate FROM Sales.Orders WHERE custid = 2;
参考文档
SCOPE_IDENTITY (Transact-SQL)
https://msdn.microsoft.com/zh-cn/library/ms190315.aspx
@@IDENTITY (Transact-SQL)
https://msdn.microsoft.com/zh-cn/library/ms187342.aspx
IDENT_CURRENT (Transact-SQL)
https://msdn.microsoft.com/library/ms175098.aspx
CREATE SEQUENCE (Transact-SQL)