2012-04-12 62 views
30

我有一個創建整個數據庫並將所有記錄插入到幾十個表的腳本。 它工作得很好,除非在處理過程中出現問題,並且在插入過程中腳本失敗並且可以再次將其設置爲OFF之前,表將IDENTITY_INSERT置ON。爲所有表設置IDENTITY_INSERT OFF

發生這種情況時,腳本在嘗試再次運行時會自動失敗,並在我們進入第一個表的插入時發生錯誤「IDENTITY_INSERT已經爲表xx打開」。

作爲故障安全,我想確保IDENTITY_INSERT在所有表中設置爲OFF,然後在安裝腳本中運行其餘的處理。

作爲替代方案,我們也許可以關閉MS SQL連接,然後再次打開它,它,我的理解是,將清除所有IDENTITY_INSERT值的連接會話。

什麼是最好的方式來做到這一點,並防止「已經上」的錯誤?

+0

什麼版本的SQL Server? – 2012-04-12 03:03:14

+0

此應用程序需要工作w/2005及以上,所以理想的解決方案,適用於所有最新和即將推出的版本。 – 2012-04-12 04:48:37

+0

我的解決方案應該可以在05和更高版本中使用。 – 2012-04-12 12:03:40

回答

18
EXEC sp_MSforeachtable @command1="SET IDENTITY_INSERT ? OFF" 
+3

我很喜歡這個......除此之外,並不是這個數據庫中的每個表都有一個標識字段,所以這個失敗了。否則我懷疑它會是完美的。 – 2012-04-12 05:37:31

+1

根據http://technet.microsoft.com/en-us/library/aa259221(v=sql.80),在任何時候,會話中只有一個表可以將IDENTITY_INSERT屬性設置爲ON。aspx#feedback – qub1n 2014-04-24 14:29:19

+1

@ qub1n OP沒有要求將屬性設置爲ON。 – 2014-04-24 15:03:13

36

動態SQL:

select 'set identity_insert ['+s.name+'].['+o.name+'] off' 
from sys.objects o 
inner join sys.schemas s on s.schema_id=o.schema_id 
where o.[type]='U' 
and exists(select 1 from sys.columns where object_id=o.object_id and is_identity=1) 

然後複製&生成的SQL粘貼到另一個查詢窗口,並運行

+0

要分享這個,不錯的把戲無論如何:) – ktutnik 2012-11-28 08:33:01

+0

哇,這節省了我的培根。謝謝! – 2013-08-21 17:57:31

+0

我想從我的代碼中獲得批量數據庫插入。你能提出一些如何在jpa中實現的建議嗎? – muasif80 2015-03-11 17:11:20

5
EXEC sp_MSforeachtable @command1="PRINT '?'; SET IDENTITY_INSERT ? OFF", 
@whereand = ' AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = o.id AND is_identity = 1)' 

大廈琳的回答,如果你懶得在多個步驟中執行此操作 - 這應該在有標識列的所有表上運行。

需要注意的是隻有在2012年和sp_MSforeachtable當然是完全不被支持的測試...

+0

也適用於Sql Server 2014和2016 – 2017-10-18 15:49:20

1

大廈@ KevD的答案 - 這是工作的罰款禁用,但這裏更多的是用於啓用爲好。

要禁用,他們需要禁用所有身份插入,使用 -

EXEC sp_MSforeachtable @command1="PRINT '?'; SET IDENTITY_INSERT ? OFF", 
@whereand = ' AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = o.id 
AND is_identity = 1) and o.type = ''U''' 

爲了使他們需要啓用所有身份插入,使用 -

EXEC sp_MSforeachtable @command1="PRINT '?'; SET IDENTITY_INSERT ? ON", 
@whereand = ' AND EXISTS (SELECT 1 FROM sys.columns WHERE object_id = o.id 
AND is_identity = 1) and o.type = ''U''' 

測試SQL Server上2014年和2016年

0

我有一個類似的問題,但我寧願不在生產中使用未記錄的存儲過程。爲了實現這一點,我建立了@John Dewey的答案並將其放入光標中。這在407毫秒內迭代超過699個表。

DECLARE @sql NVARCHAR(500) -- SQL command to execute 

DECLARE sql_cursor CURSOR LOCAL FAST_FORWARD FOR 
SELECT 'SET identity_insert ['+s.name+'].['+o.name+'] OFF' 
FROM sys.objects o 
INNER JOIN sys.schemas s on s.schema_id=o.schema_id 
WHERE o.[type]='U' 
AND EXISTS(SELECT 1 FROM sys.columns WHERE object_id=o.object_id AND is_identity=1) 

OPEN sql_cursor 
FETCH NEXT FROM sql_cursor INTO @sql 

WHILE @@FETCH_STATUS = 0 
    BEGIN 
     EXECUTE sp_executesql @sql --> Comment this out to test 
     -- PRINT @sql --> Uncomment to test or if logging is desired 
     FETCH NEXT FROM sql_cursor INTO @sql 
    END 

CLOSE sql_cursor 
DEALLOCATE sql_cursor 

如果你反對遊標,它也可以很容易地轉換成while循環。

相關問題