在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)