列属性:RowGUIDCol、Identity 和 not for replication
在SQL Server中,创建数据表,需要为表设置合适的属性和约束,例如,自增列,非空,主键等,以满足业务的需求,一般来说,数据表存储的实体都应该唯一标识,使用ID列或GUID列来充当候选主键是可以的,相应地,数据表的列(Column)有两个特殊的属性:
- RowGUIDCol:用于标识UniqueIdentifier 类型的数据列,该列可以通过内置函数 $ROWGUID 来引用;
- Identity:用于标识整数类型(int,bigint,tinyint,smallint,decimal(p,0))的列是自增列,该列可以通过内置函数$IDENTITY 来引用;
在每个表中,只能有一列被标识为RowGUIDCol,只能有一列被标识为Identity;
一,属性说明
1,自增属性
自增属性的定义是IDENTITY(seed,increment),属性Identity标识的列是自增列,每个表只能有一个自增列。Identity属性必须设置两个参数seed和increment,默认值是:seed=1,increment=1,即Identity(1,1),seed参数是自增列的第一个值,increment参数是每次数据增加的大小。例如,IDENTITY(2,3) 表示,自增列的第一个值是2,每次增加3,第二个值是5,第三个值是8,等等。当向表中插入数据行时,数据库引擎自动向该列中插入唯一的,递增的整数值。
<column_definition> ::= column_name <data_type> [ NULL | NOT NULL ] IDENTITY [ ( seed ,increment ) ] [ NOT FOR REPLICATION ]
2,属性 ROWGUIDCOL
属性RowGUIDCol标识一个数据列是GUID列,数据表中可以有多个UniqueIdentifier类型数据列,但是每个表中只能有一个UniqueIdentifier数据列被标识为RowGUIDCol列。如果列被指定属性RowGUIDCol,那么可以通过$ROWGUID引用,不需要通过列名来引用。
3,引用属性标记的数据列
当访问被属性RowGUIDCol和Identity标记的数据列时,可以通过函数$RowGUID和$Identity来引用,不需要通过列名:
CREATE TABLE dbo.myTable_RowGUIDCol ( ColumnA uniqueidentifier ROWGUIDCOL not null constraint DF__myTable_RowGUIDCol_ColumnA DEFAULT NewID(), ColumnB int identity, columnC varchar(10) ) insert into dbo.myTable_RowGUIDCol(columnC) values('test') select $ROWGUID,$IDENTITY from dbo.myTable_RowGUIDCol
二,显式向自增列插入值
默认情况下,不能向IDENTITY列中插入数值。一般来说,在向数据表中插入新的数据行时,由数据库引擎自动向自增列中插入唯一的,递增的正整数值。
当想要手动向自增列中插入指定的数值,必须设置表的 Identity_Insert选项为ON。
SET IDENTITY_INSERT schema_name.table_name ON | OFF
1,启用该选项时,必须注意:
- 在插入数据值,必须在Insert子句中显式指定Table的所有Column;
- 如果插入值比当前的ID值大,那么SQL Server自动使用插入值作为新的ID值;
set IDENTITY_INSERT dbo.myTable_RowGUIDCol ON insert into dbo.myTable_RowGUIDCol (ColumnA,ColumnB,columnC) values(newid(),3,'test2') set IDENTITY_INSERT dbo.myTable_RowGUIDCol Off insert into dbo.myTable_RowGUIDCol(columnC) values('test3') select ColumnA,ColumnB,columnC from myTable_RowGUIDCol
2,创建示例数据
create table dbo.ta ( id int identity(1,1) not null, name varchar(10) null ) insert into dbo.ta values(1,'a')
出现错误: An explicit value for the identity column in table 'dbo.ta' can only be specified when a column list is used and IDENTITY_INSERT is ON.
2.1,将选项 IDENTITY_INSERT 设置为ON
set IDENTITY_INSERT dbo.ta on
2.2,显式向ID列赋值
insert into dbo.ta values(1,'a')
由于没有在Insert子句中,显式列出table的所有column,SQL Server Engine抛出错误:
An explicit value for the identity column in table 'dbo.ta' can only be specified when a column list is used and IDENTITY_INSERT is ON.
2.3,显式列出Target Table的所有column
insert into dbo.ta(id,name) values(1,'a')
三,RowGUIDCol 和 Identity 的比较
1,自增性
属性Identity 标识的整数类型的Column 具有自动增长的特点,除非设置SET IDENTITY_INSERT ON,否者,不能显式对自增列赋值。
RowGUIDCol属性 用于标识UniqueIdentifier 列,唯一的作用是能够使用$ROWGUID引用。没有自动增长的特性,必须显式赋值,或者创建Default 约束,使用默认值赋值。对UniqueIdentifier 列赋值有两种方式:
- 使用NewID(),NewSequentialID() 函数赋值;
- 特定格式的字符串:‘xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx’,x是16进制数值,按照数字的位数,格式是:8-4-4-4-12,共32个数字,4个中划线;
2,“唯一”的范围
在一个表中,ID列的值是唯一的,不同表的ID列的值可能相同;
如果使用NewID(),或 NewSequentialID() 函数赋值对UniqueIdentifier列赋值,那么在整个服务器内,所有UniqueIdentifier列的值是唯一的,即在同一个服务器的数据库中,不同数据表的GUID列(使用NewID(),或 NewSequentialID() 函数赋值)的值是不相同的。
四,ID列的Not For Replication
Identity列的值是SQL Server Engine自动生成的,唯一的,递增的整数值。默认情况下,用户不能显式插入数值。当启用表的复制(Replication)时,ID列被复制/同步到其他订阅表中,如何使两个表的ID列值保持一致?SQL Server提供的做法是:在创建订阅数据表时,为ID列指定 not for replication 属性。当分发代理(distribution agent)执行Insert 命令时,ID列被显式赋值,并且ID列的标识值不会自增,跟普通的整数列的行为相同。
在发布端中,虽然Identity列不需要指定Not For Replication属性,但是,由于快照复制(Snapshot Replication)能够把发布端(Publisher)中 Identity列的 not for replication属性复制到Subscriber中,因此,建议在发布端中创建数据表时,为Identity列指定Not For Replication属性。在事务复制中,如果没有为ID列指定 not for replication 属性,那么每次插入数据时,不管Insert 操作是失败还是成功,其ID列的标识值都会自增。
Not For Replication属性有两个作用:
- 在事务复制中,Distribution能够对Subscriber Table中的ID列赋值,保持两个ID列数据的同步;
- 在事务复制中,通过Distribution对Subscriber Table中的ID列赋值,该ID列的标识值不变;
如果显式对ID列赋值,并且该值大于当前ID列的标识值,那么ID列的标识列变为该值;如果显式对该表执行Insert操作,那么,ID列的标识值将增加。
例如,假如TableA的ID列名是EventID,该列具有not for replication属性,
create table dbo.TableA ( EventID int not null identity(1,1) not for replication ,
name varchar(10) null
)
通过Replication同步到该列的最大值是100,但是该列的标识值不变,仍然是1。如果向该表中插入数据,那么,第一个ID值是1,第二个ID值是2,依次类推。
参考文档:
IDENTITY (Property) (Transact-SQL)