亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

10. IDENTITY屬性使用小結

2024-07-21 02:49:53
字體:
來源:轉載
供稿:網友
10. IDENTITY屬性使用小結

從SQL Server 2012開始有了Sequence,簡單用列如下:

CREATE SEQUENCE TestSeqSTART WITH 1INCREMENT BY 1 ;SELECT NEXT VALUE FOR TestSeq AS NextValue;

在這之前,表中生成序列號大多都是借助IDENTITY列屬性,當然也有一些時候,是在自定義表中,自己維護序列號。

一. 創建IDENTITY列

if OBJECT_ID('test','U') is not null    drop table testGOcreate table test(id int identity, c1 char(1))insert test values('a');insert test values('b');select * from test

1. 沒有指定IDENTITY(seed ,increment),默認就是 IDENTITY(1, 1),效果同如下語句

create table test(id int identity(1,1), c1 char(1))

2. 通過函數或者系統視圖,都可以查看是否為IDENTITY列

SELECT COLUMNPROPERTY(OBJECT_ID('test'),'id','IsIdentity') AS is_identityselect object_name(object_id) as table_name, is_identity,* from sys.columns where object_id=object_id('test') --and is_identity=1

3. 重置IDENTITY列的初始值,通常在數據刪除/歸檔后進行

DELETE testDBCC CHECKIDENT('test', RESEED, 1)DBCC CHECKIDENT('test', NORESEED)--TRUNCATE表后會自動重置IDENTITY列TRUNCATE TABLE testDBCC CHECKIDENT('test', NORESEED)

二. 獲取IDENTITY列值插入了數據,有時還需要獲取剛才生成的序列值另作他用,返回給前端也好,或者插入其他將來需要關聯的表。

記得曾經有個面試題:假設當前表IDENTITY列最大值為N,在存儲過程中,對這個表插入1行數據,獲取到的IDENTITY列值有時小于或者大于N+1,可能是什么原因?

獲取IDENTITY列值有三種方式:(1) IDENT_CURRENT( 'table_name' ) 返回為任何會話和任何作用域中的特定表最后生成的標識值。(2) @@IDENTITY 返回為當前會話的所有作用域中的任何表最后生成的標識值。(3) SCOPE_IDENTITY() 返回為當前會話和當前作用域中的任何表最后生成的標識值。

IDENT_CURRENT( 'table_name' ) 針對特定表,是全局的。@@IDENTITY和SCOPE_IDENTITY()針對所有表,區別在于作用域,也就是上下文:(1) 如果當前INSERT語句上有函數,觸發器等(不同作用域的)對象返回的IDENTITY值,那么@@IDENTITY會取所有表上的最后1個,而不是當前表上的;

(2) SCOPE_IDENTITY()會取當前作用域所有表上最后1個IDENTITY值,被調用的函數,觸發器已經超出了作用域/上下文。所以在使用INSERT后,接著使用SCOPE_IDENTITY()獲取IDENTITY列值,就不會有問題了:

insert test values('z');select SCOPE_IDENTITY() as curr_value

一個GO語句/批處理,也是一個上下文的分界點,但是SQL語句是順序執行的,所以一個會話里,只要在INSERT之后用SCOPE_IDENTITY()來獲取IDENTITY值是沒問題的。

三. 修改IDENTITY列值/屬性1. 對已存在的列增加/刪除IDENTITY屬性

if OBJECT_ID('t_id') is not nulldrop table t_idGOcreate table t_id(id int,c1 char(1))insert into t_idselect 1,'a' union allselect 2,'b'alter table t_id alter column id int identity(1,2)/*Msg 156, Level 15, State 1, Line 2Incorrect syntax near the keyWord 'identity'.*/

直接修改列屬性會報錯,IDENTITY屬性只能伴隨著列增加/刪除。

(1) 利用中間表在SSMS界面上設計表(SSMS/Tables/Design),可以直接增加/刪除列上的IDENTITY屬性,如果生成腳本看看的話(右擊編輯框/工具欄/菜單欄),可以發現SSMS是利用了中間表,并非在原表直接修改屬性。

表上有約束,索引等對象時,腳本會更加繁雜些。示例如下圖:

如果出現如下錯誤:Saving changes is not permitted. The changes that you have made require the following tables to be dropped and re-created. You have either made changes to a table that can't be re-created or enabled the option Prevent saving changes that require the table to be re-created.

是因為SSMS里有個選項沒設置,SQL Server認為有刪除/重建表的腳本不安全,所以默認關閉了,需要手動開啟一下,去掉那個勾:

對表上已存在列添加IDENTITY屬性,生成的腳本如下:

BEGIN TRANSACTIONSET QUOTED_IDENTIFIER ONSET ARITHABORT ONSET NUMERIC_ROUNDABORT OFFSET CONCAT_NULL_YIELDS_NULL ONSET ANSI_NULLS ONSET ANSI_PADDING ONSET ANSI_WARNINGS ONCOMMITBEGIN TRANSACTIONGOCREATE TABLE dbo.Tmp_t_id    (    id int NOT NULL IDENTITY (1, 1),    c1 char(1) NULL    )  ON [PRIMARY]GOALTER TABLE dbo.Tmp_t_id SET (LOCK_ESCALATION = TABLE)GOSET IDENTITY_INSERT dbo.Tmp_t_id ONGOIF EXISTS(SELECT * FROM dbo.t_id)     EXEC('INSERT INTO dbo.Tmp_t_id (id, c1)        SELECT id, c1 FROM dbo.t_id WITH (HOLDLOCK TABLOCKX)')GOSET IDENTITY_INSERT dbo.Tmp_t_id OFFGODROP TABLE dbo.t_idGOEXECUTE sp_rename N'dbo.Tmp_t_id', N't_id', 'OBJECT' GOCOMMIT

對表上已存在列刪除IDENTITY屬性,生成的腳本如下:

BEGIN TRANSACTIONSET QUOTED_IDENTIFIER ONSET ARITHABORT ONSET NUMERIC_ROUNDABORT OFFSET CONCAT_NULL_YIELDS_NULL ONSET ANSI_NULLS ONSET ANSI_PADDING ONSET ANSI_WARNINGS ONCOMMITBEGIN TRANSACTIONGOCREATE TABLE dbo.Tmp_t_id    (    id int NOT NULL,    c1 char(1) NULL    )  ON [PRIMARY]GOALTER TABLE dbo.Tmp_t_id SET (LOCK_ESCALATION = TABLE)GOIF EXISTS(SELECT * FROM dbo.t_id)     EXEC('INSERT INTO dbo.Tmp_t_id (id, c1)        SELECT id, c1 FROM dbo.t_id WITH (HOLDLOCK TABLOCKX)')GODROP TABLE dbo.t_idGOEXECUTE sp_rename N'dbo.Tmp_t_id', N't_id', 'OBJECT' GOCOMMIT

(2) 利用中間列對表上已存在列刪除IDENTITY屬性

if OBJECT_ID('t_id') is not null    drop table t_idGOcreate table t_id(id int identity(1,1),c1 char(1))insert into t_idselect 'a' union allselect 'b'select * from t_idSELECT COLUMNPROPERTY(OBJECT_ID('t_id'),'id','IsIdentity')--在表上新增一個列,把IDENTITY列值復制過去alter table t_id add id_new intGOupdate t_id set id_new = id--刪除原來的列,并重命名新增列alter table t_id drop column idexec sp_rename 't_id.id_new','id'select * from t_idSELECT COLUMNPROPERTY(OBJECT_ID('t_id'),'id','IsIdentity')

對表上已存在列添加IDENTITY屬性,用中間列的方式不太可行,因為IDENTITY列不接受UPDATE,新增的IDENTITY列無法直接復制原id的值,還得借助中間表,但如果不需要原來id的值,那么可以:

if OBJECT_ID('t_id') is not null    drop table t_idGOcreate table t_id(id int,c1 char(1))insert into t_idselect 1,'a' union allselect 3,'b'select * from t_idSELECT COLUMNPROPERTY(OBJECT_ID('t_id'),'id','IsIdentity')--在表上新增一個IDENTITY列,不復制原來的ID值alter table t_id add id_new int identity(1,1) not null --刪除原來的列,并重命名新增列alter table t_id drop column idexec sp_rename 't_id.id_new','id'select * from t_idSELECT COLUMNPROPERTY(OBJECT_ID('t_id'),'id','IsIdentity')

2. 在IDENTITY列上做增刪改操作(DML)(1) 刪除操作沒有問題,直接DELETE即可

delete test where id = 2

(2) 如果要顯式INSERT某個值,需要開啟IDENTITY_INSERT這個session級的選項

set IDENTITY_INSERT test on;insert test(id,c1) values(3,'c');set IDENTITY_INSERT test off;select * from test

(3) 如果要UPDATE IDENTITY列值,無論是否開啟IDENTITY_INSERT這個選項都無法更新

set IDENTITY_INSERT test on;update test set id = 10 where id = 1set IDENTITY_INSERT test off;/*Msg 8102, Level 16, State 1, Line 1Cannot update identity column 'id'.*/

非要修改的話,就得借助中間表,在不含IDENTITY屬性的中間表里做完UPDATE,然后再把數據導回來。中間表可參考上面的腳本。

3. IDENTITY列屬性復制(1) 直接從單表SELECT INTO table_name,原表其他約束,索引等等都不會被復制,但是IDENTITY屬性會被復制。

select * into test2 from testselect * from test2select columnproperty(OBJECT_ID('test'),'id','IsIdentity')select columnproperty(OBJECT_ID('test2'),'id','IsIdentity')

(2) 如果有IDENTITY屬性的表和其他表JOIN,那么IDENTITY屬性不會被復制。

select a.* into test3 from test a inner join sys.objects bon a.id = b.object_idselect * from test3select columnproperty(OBJECT_ID('test3'),'id','IsIdentity')

假如復制表時,不想要IDENTITY屬性,正好可以利用一下這個特點,如下:

select a.* into test4from test a inner join sys.objects bon 1=2

(3) 如果用SELECT INTO table_name導數據時,FROM子句有多表關聯,且想要保留IDENTITY屬性,這時可以用INSERT,并考慮使用TABLOCK提示

if OBJECT_ID('test5','U') is not nulldrop table test5GOcreate table test5(id int identity, c1 char(1))select * from test5GOset IDENTITY_INSERT test5 on;insert into test5 WITH(TABLOCK) (id,c1)select a.* from test a inner join test2 b on a.id = b.idset IDENTITY_INSERT test5 off;select * from test5select columnproperty(OBJECT_ID('test5'),'id','IsIdentity')

這里使用了WITH(TABLOCK)選項,在SIMPLE或者BULK_LOGGED恢復模式下,SELECT…INTO table_name和INSERT INTO table_name WITH(TABLOCK)都能最小化日志。

4. 借助SWITCH來處理IDENTITY屬性,推薦同樣也是利用中間表,上面的幾個列子都使用了INSERT,這里使用SWITCH,不再有數據倒來倒去的開銷,需要SQL Server 2008及以上版本,能比較有效地同時解決上面的3個問題:(1) 不能直接對表上現有列增加/刪除IDENTITY屬性;(2) 不能直接更新IDENTITY列;(3) 復制表時,有選擇的復制IDENTITY列屬性(多表關聯,對關聯后的表做SWITCH以實現);

CREATE TABLE Temp1(ID INT IDENTITY(1,1) PRIMARY KEY,X VARCHAR(10))INSERT INTO Temp1 OUTPUT INSERTED.*SELECT 'Foo' UNION ALLSELECT 'Bar' UNION ALLSELECT 'Baz'CREATE TABLE Temp2(ID INT PRIMARY KEY,X VARCHAR(10))ALTER TABLE Temp1 SWITCH TO Temp2;SELECT COLUMNPROPERTY(OBJECT_ID('Temp1'),'id','IsIdentity')SELECT COLUMNPROPERTY(OBJECT_ID('Temp2'),'id','IsIdentity')INSERT INTO Temp2OUTPUT INSERTED.*SELECT 10,'Foo' UNION ALLSELECT 20,'Bar' UNION ALLSELECT 5, 'Baz'UPDATE Temp2 SET ID = ID + 1;ALTER TABLE Temp2 SWITCH TO Temp1;SELECT * FROM Temp2SELECT * FROM Temp1<
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲aaaaaa| 成人免费视频网址| 日韩精品免费看| 欧美精品第一页在线播放| 亚洲人成电影网站色…| 亚洲欧洲日韩国产| 欧美性猛交视频| 青青青国产精品一区二区| 国产免费一区二区三区在线能观看| 欧美激情免费看| 久久视频精品在线| 精品国产鲁一鲁一区二区张丽| 亚洲国产另类 国产精品国产免费| 日韩国产精品一区| 欧美精品在线免费播放| 久久精品国产69国产精品亚洲| 久久国产精品影片| 欧美性开放视频| 欧美一级电影在线| 久久久久久久久中文字幕| 综合136福利视频在线| 久久久免费高清电视剧观看| 日韩国产精品视频| 亚洲性生活视频在线观看| 欧美整片在线观看| 国产成人中文字幕| 久久久精品影院| 成人女保姆的销魂服务| 日韩有码视频在线| 久久久www成人免费精品| 欧美另类69精品久久久久9999| 欧美贵妇videos办公室| 欧美日韩福利电影| 国产精品爽爽爽爽爽爽在线观看| 国产免费一区二区三区在线能观看| 日韩影视在线观看| 亚洲人成网站色ww在线| 久久久伊人欧美| 日韩欧美精品免费在线| 亚洲天堂av在线免费观看| 国产一区二区三区四区福利| 美女啪啪无遮挡免费久久网站| 精品久久久免费| 国产精品无码专区在线观看| xxx一区二区| 久久久999国产| 欧美黑人xxx| 亚洲图片欧美日产| 九九久久精品一区| 日韩av网址在线观看| 欧美黄网免费在线观看| 国产日韩欧美中文在线播放| 日韩av片免费在线观看| 久久精品一偷一偷国产| 国产精品免费视频久久久| 亚洲欧洲日产国码av系列天堂| 国产欧美韩国高清| 中文字幕视频一区二区在线有码| 久久天天躁夜夜躁狠狠躁2022| 国产美女直播视频一区| 亚洲精品自拍第一页| 人妖精品videosex性欧美| 91精品国产综合久久久久久蜜臀| 伊人一区二区三区久久精品| 国产日韩在线免费| 亚洲成人a级网| 2018日韩中文字幕| 亚洲精品国产精品国自产观看浪潮| 91精品国产91久久久| 欧美亚洲视频在线看网址| 日韩激情在线视频| 亚洲一区中文字幕在线观看| 国产一区欧美二区三区| 欧美在线视频免费| 北条麻妃99精品青青久久| 91在线观看免费网站| 亲爱的老师9免费观看全集电视剧| 欧美另类老女人| 97精品国产97久久久久久| 中文字幕亚洲字幕| 亚洲国产精品女人久久久| 亚洲第一页中文字幕| 欧美福利小视频| 久久人91精品久久久久久不卡| 性欧美xxxx视频在线观看| 亚洲伊人久久综合| 国产精品成人久久久久| 97精品一区二区视频在线观看| 亚洲综合社区网| 欧美日韩国产中字| 日韩美女视频中文字幕| 欧美亚洲日本黄色| 久久久久久久久久亚洲| 宅男66日本亚洲欧美视频| 另类专区欧美制服同性| 国产精品www色诱视频| 夜夜嗨av一区二区三区免费区| 成人亚洲欧美一区二区三区| 亚洲视频在线免费观看| 亚洲女人天堂成人av在线| 亚洲国产免费av| 亚洲va久久久噜噜噜久久天堂| 国产成人精品亚洲精品| 北条麻妃一区二区在线观看| 日本亚洲欧美成人| 精品久久久av| 成人激情黄色网| 欧美日韩性视频在线| 久久影视三级福利片| 亚洲一区二区在线| 在线一区二区日韩| 8090成年在线看片午夜| 亚洲成色999久久网站| 亚洲欧美日韩精品久久| 亚洲欧洲国产一区| 国产精品高潮呻吟视频| 成人午夜在线视频一区| 色综合亚洲精品激情狠狠| 成人激情在线观看| 欧美高清无遮挡| 亚洲男女性事视频| 国产精品2018| 狠狠干狠狠久久| 国产精品视频免费在线| 亚洲天堂一区二区三区| 一区二区三区四区在线观看视频| 国产有码一区二区| 欧美日韩精品在线播放| 91精品国产91久久久久久| 国产又爽又黄的激情精品视频| 欧美国产第一页| yw.139尤物在线精品视频| 一个人看的www欧美| 久青草国产97香蕉在线视频| 欧美巨乳美女视频| 美女视频久久黄| 国产精品免费久久久久影院| 亚洲欧洲午夜一线一品| 欧美日韩亚洲视频一区| 日韩国产精品亚洲а∨天堂免| 2018国产精品视频| 国产精品高潮呻吟视频| 国产主播欧美精品| 亚洲成人av中文字幕| 91av在线免费观看| 一区二区三区久久精品| 日韩网站在线观看| 欧美最猛黑人xxxx黑人猛叫黄| 超碰91人人草人人干| 国产xxx69麻豆国语对白| 97视频免费看| 国产精品成人免费视频| 在线视频亚洲欧美| 日韩av一区在线| 欧美成人中文字幕在线| 这里精品视频免费| 亚洲丝袜在线视频| 亚洲国产日韩一区| 久久91精品国产91久久跳| 一区二区三区国产视频| 国产精品jizz在线观看麻豆| 国产性猛交xxxx免费看久久| 久久久爽爽爽美女图片| 国产精品日韩在线|