笔记246 在SQLServer中,支持多种自动产生序号的机制  黄2013-4-18

1 --在SQLServer中,支持多种自动产生序号的机制  master黄2013-4-18
--
  2 
  3 --(1)第一种是根据数据的插入自动生成序号用于识别每个数据行。称为【Identity】。作用在同一个表层面
  4 
  5 --。
  6 
  7 --(2)第二种是作用在数据库层面,叫做timestamp数据类型,称为rowversion。通过这个,可以让相同数据库中不同数据列产生唯一识别码。
  8 
  9 --
 10 
 11 --(3)第三种是似乎用NEWID()或NEWSEQUENTIALID()产生Uniqueidentifier的数据类型。这个类型是全球级别的唯一识别码。号称3000年内不会重复。
 12 
 13 --
 14 
 15 --
 16 
 17 --合理使用上面三钟方式,能减轻应用程序的负担。
 18 
 19 -----------------------------------------------------------------
 20 
 21 --1、数据表级别识别——Identity:
 22 
 23 --这种识别方式只适合在表级别。使用时只需要在insert语句中搭配即可,不用指定该列的名称。另外,它会自动增加,比如在DELETE语句中删除某行,后续的数据仍然会从最近的一行序号中自加。而不会从原始的定义起始开始重新自增。以下给出一个例子:
 24 
 25 
 26 
 27 use tempdb
 28 go
 29 --创建测试用的数据表
 30 create table Employee
 31 (
 32 en int not null IDENTITY PRIMARY KEY,     --自增ID 主键PRIMARY KEY
 33 ename varchar(50),               --员工名称
 34 keyDT datetime          --创建日期
 35 )
 36 
 37 --DROP TABLE [dbo].[Employee]
 38 
 39 
 40 --插入数据,不指定列名
 41 insert into Employee
 42 values('Lewis','2012/6/23');
 43 
 44 --插入数据,指定列名,但不指定自增列
 45 insert into Employee(ename,keyDT)
 46 values('Ada','2012/6/24')
 47 go
 48 select * from Employee
 49 
 50 -----------------------------------------------------
 51 --针对Identity,还有一些使用技巧:
 52 
 53 --1、Identity(n,m):n为自增起始值,m为自增数量,可以实现(n,n+m,n+2m,n+3m..)这样的数据。
 54 
 55 --2、@@identity系统函数:该用处在执行阶段,用于捕获最近一次插入数据所产生的自增号。在应用程序中非常有用,比如新增一个新数据,然后获取该id,接着用于查询显示。
 56 
 57 --3、IDENT_CURRENT('数据表名'):可以找出指定表的目前最大自增号,可以取代SELECT MAX语句,加快查询。特别是在大并发的时候,如果用SELECT MAX可能会出现获取不正确的序号,而且当表非常大的时候SELECT MAX也是需要很长时间的。
 58 
 59 --4、SCOPE_IDENTITY()函数:在存储过程、触发器执行过程中的自增加号数。但和@@identity有些不同,@@identity返回的是整个事务中的目前值,而本函数仅返回该存储过程、触发器程序中的新增数据表的号码。@@identity在一个事务有延伸或调用另外一个表的INDENTITY属性时,会产生差异,而本函数主要用于处理这种问题。
 60 
 61 ---------------------------------------------------------------
 62 
 63 --2、数据库级别标识——timestamp :
 64 
 65 --这个功能主要使用数据库的计数器产生的时间戳,产生每个数据的识别。这种数据的属性是timestamp,也称为rowversion。为指定数据库的任何数据表产生唯一的戳值。戳值就是一种二进制数据类型,长度等于varbinary(8)。另外,这种类型还会根据后续针对这行数据的修改,改变原有timestamp值。由于它的动态性,在选作索引值时要评估。
 66 
 67 --该值可以使用@@DBTS系统函数来获取。
 68 
 69 --以下是示例代码:
 70 
 71 use tempdb
 72 go
 73 --创建南方员工的数据表
 74 CREATE TABLE Employee_S
 75 (
 76      en timestamp not null,--自增二进制ID
 77      ename varchar(50),--员工名
 78      keyDT datetime     --创建时间
 79 )
 80 
 81 --创建中部员工的数据表
 82 CREATE TABLE Employee_C
 83 (
 84      en timestamp not null,--自增二进制ID
 85      ename varchar(50),--员工名
 86      keyDT datetime     --创建时间
 87 )
 88 
 89 --创建北方员工的数据表
 90 CREATE TABLE Employee_N
 91 (
 92      en timestamp not null,--自增二进制ID
 93      ename varchar(50),--员工名
 94      keyDT datetime     --创建时间
 95 )
 96 
 97 --插入数据:
 98 insert into Employee_S(ename,keyDT) values('Sname',GETDATE())
 99 insert into Employee_C(ename,keyDT) values('Cname',GETDATE())
100 insert into Employee_N(ename,keyDT) values('Yname',GETDATE())
101 --显示数据
102 select '南方',* from Employee_S
103 union all
104 select '中部',* from Employee_C
105 union all
106 select '北方',* from Employee_N
107 
108 --执行脚本后看到数据的日期是一样的,但是en列不一样,而这种效果是identity做不到的
109 --timestamp在多个表之间保持唯一
110 
111 -------------------------------------------------------------------
112 --3、使用NEWID()搭配UniqueIdentifier数据产生全球唯一标识码:
113 
114 --该值通过随机搭配多种配置信息,产生全球性的唯一识别码。以下是一个示例代码
115 
116 use tempdb
117 go
118 --创建南方员工的数据表
119 CREATE TABLE Employee_GUID
120 (
121      en uniqueidentifier not null,--自增二进制ID
122      ename varchar(50)--员工名
123 
124 )
125 
126 --插入数据:
127 insert into Employee_GUID(en,ename) values(newid(),'Sname')
128 insert into Employee_GUID(en,ename) values(newid(),'Cname')
129 insert into Employee_GUID(en,ename) values(newid(),'Nname')
130 
131 
132 --显示数据,为了证明不唯一,可以使用GROUP BY来检验:
133 --源数据
134 select *
135 from Employee_GUID
136 --检验数据
137 select count(1) 'Total',en
138 from Employee_GUID
139 group by en
140 having count(1)>1
141 
142 
143 --另外,在前面提到过,可以使用NEWID()和NEWSEQUENTIALID()产生, 考虑NEWID()和NEWSEQUENTIALID()两者在使用上的区别:
144 use tempdb
145 go
146 --产生NEWID()和NEWSEQUENTIALID():
147 SET NOCOUNT ON
148 DECLARE @T TABLE (newSN uniqueidentifier,seqSN uniqueidentifier default (NEWSEQUENTIALID()))
149 DECLARE @I INT
150 SET @I=1
151 WHILE @I<=10
152 BEGIN
153      INSERT INTO @T VALUES(NEWID(),DEFAULT)
154           SET @I=@I+1
155 END
156 
157 SELECT * FROM @T
158 SET NOCOUNT OFF
159 
160 --执行后可以看到下图:注意每台机器值会不一样
161 --从图上可以看出,NEWSEQUENTIALID()会产生一个有次序的GUID值(观察值的第一部分),这样可以在做比较时起作用。而NEWID()则为没有次序的值。
162 
163 
164 --注意事项:
165 
166 --1、使用Identity作为行的标识时,无法结合事务的使用保留下一个使用的号码。即当事务发生Rollback时,依然会出去一个号码,而不会释放,会造成跳号现象。
167 
168 --2、使用Truncate会重置IDENTITY最后识别的值。而DELETE全部删除数据,但下一行数据依旧会从原有的上一笔开始,不会重新开始。
169 
170 --3、使用Timestamp类型时,仅适合那些不会UPDATE操作的数据。因为会更新timestamp值。
171 
172 
173 
174 
175 
176 --博客园里的开辟数据同步软件
177 
178 --
179 
180 --程序使用注意事项
181 
182 --1.必须确保您的数据库没有修改主键的操作。由于修改主键会引起很多问题,如果一定要修改主键,建议把修改拆分成删除→添加。
183 
184 --
185 
186 --2.必须确保您的数据库没有使用自增长的字段,因为自增长字段本程序无法干涉。
187 
188 --
189 
190 --3.支持所有SQL数据类型(除SQL2008新增的geography、geometry、hierarchyid)。
191 
192 --
193 
194 --4.数据库连接字符串一旦成功设置,不能更改!如需更改,需要重新安装程序。