2012-05-17 407 views
51

我已經搜索了這個,但它出現的線程往往有不明白問題的人的答案。如何檢查SQL Server中IDENTITY_INSERT是否設置爲ON或OFF?

採取的語法如下:

SET IDENTITY_INSERT Table1 ON 

你如何做更多的事情是這樣的:

GET IDENTITY_INSERT Table1 

我不想做任何事情在數據庫或數據設置來獲取這些信息。謝謝!

+2

有趣的是,你是如何提到人們誤解這個問題以及絕大多數答案的,這樣做的確如此。 – Fishcake

+2

對於你和其他人用google搜索這個,真正的問題:*會議*。您可能只想檢查/恢復IDENTITY_INSERT的* session *值,並且足夠複雜,以允許和稍後防止身份插入。 (連續運行的作業步驟?)因爲如果你開始一個新的會話,'IDENTITY_INSERT'已關閉!如果你不清楚是否某個會話保持不變,google會話(不完全是=連接),請查看sys.dm_exec_sessions和sys.dm_exec_connections,或者下載sp_WhoIsActive和EXEC sp_WhoIsActive @show_sleeping_spids = 2, @show_own_spid = 1' –

回答

25

由於SET IDENTITY_INSERT是會話敏感的,因此它在緩衝級別進行管理而不存儲在某處。這意味着我們不需要檢查IDENTITY_INSERT狀態,因爲我們從不在當前會話中使用此關鍵字。

對不起,沒有幫助。

大問題,雖然:)

來源:Here

更新 有辦法也許要做到這一點,也可見於我聯繫該網站,國際海事組織,實在是太努力成爲有用。

if 

(select max(id) from MyTable) < (select max(id) from inserted) 

--Then you may be inserting a record normally 

BEGIN 
    set @I = 1 --SQL wants something to happen in the "IF" side of an IF/ELSE 
END 

ELSE --You definitely have IDENTITY_INSERT on. Done as ELSE instead of the other way around so that if there is no inserted table, it will run anyway 


BEGIN 
.... Code that shouldn't run with IDENTITY_INSERT on 
END 
+0

謝謝。我剛剛纔知道它是昨天存在的,所以我不確定如何應用你所說的話。基本上我們有兩個不同的服務器上的兩個數據庫,並關閉任何一個,然後重新啓動它將成爲一個問題。如果數據庫服務保持無限期運行,那麼您所指的會話持續多於幾分鐘?基本上我在其中一個數據庫上設置了一些值,但沒有事先做筆記,我需要確保像這樣的任何更改都會回滾。 – Panzercrisis

+1

請注意,這不是我自己的答案,但來自http://social.msdn.microsoft.com/Forums/en/transactsql/thread/1a6ba2bb-5e82-47e8-a1a0-16fc044b951e(官方微軟論壇,這些書籤有很多。)這完全取決於這些服務器的性能。顯然,如果服務器很慢/關於SQL Server的服務正在關閉,這個代碼(在僞代碼中)將無法正常工作。爲什麼你完全需要知道表的身份狀態? 如果服務無限期運行,此會話不應該持續很長時間(取決於服務器規格和表大小)... – Eon

+0

我只是試圖重置數據庫回到之前我開始搞亂IDENTITY_INSERT值。 – Panzercrisis

3

如果你想了解會話變量......好的問題,但我不能看到這個信息將是有用的。在正常執行中檢查對插入的普通表響應,這應該工作!

- 如果你只是想知道是否有標識插入一個給定表:

select is_identity 
from sys.columns 
where object_id = OBJECT_ID('MyTable', 'U') and name = 'column_Name' 

- 或者...如果你想執行根據結果的東西使用此:

if exists (select * 
from sys.columns 
where object_id = OBJECT_ID('MyTable', 'U') and is_identity = 1) 
... your code considering identity insert 
else 
... code that should not run with identity insert 

玩得開心!

+5

這沒有說明問題,問題是關於'IDENTITY_INSERT'是否打開,如果表有一個標識列 – Fishcake

+0

'sys.columns'表中的is_identity'列標識該列是否是標識列,而不是變量'IDENTITY_INSERT'是'ON'或'OFF' –

0

,你也可以使用OBJECTPROPERTY方法來確定一個表有一個標識:

DECLARE @MyTableName nvarchar(200) 
SET @MyTableName = 'TestTable' 
SELECT CASE OBJECTPROPERTY(OBJECT_ID(@MyTableName), 'TableHasIdentity') 
WHEN 1 THEN 'has identity' 
ELSE 'no identity columns' 
END as HasIdentity 
1

非常好的問題。我有同樣的問題。可能您可以嘗試使用TRY/CATCH重置IDENTITY_INSERT?例如,您創建作業,但不確定作業是否完成,IDENTITY_INSERT設置爲OFF。

爲什麼你不嘗試:

BEGIN TRY 
... 
END TRY 
BEGIN CATCH 
SET IDENTITY_INSERT table OFF; 
END CATCH; 

而且我不知道這是否正常工作,但我看到的是隻增加SET IDENTITY_INSERT ... OFF沒有返回錯誤。所以你可以設置,以防萬一到底SET IDENTITY_INSERT ... OFF

12

總結:

  • Nathan的解決方案是最快的:

    SELECT OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity'); 
    
    • 使用API​​包裝時

      ,一方面可以減少整個檢查只檢查行。在使用例如C#的SqlDataReaders財產HasRows和查詢構造,如:

      SELECT CASE OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity') 
           WHEN 1 THEN '1' ELSE NULL END 
      
  • 李嘉圖的解決方案可以讓更多的靈活性,但需要列的標識名稱

    SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('MyTable', 'U') 
             AND name = 'MyTableIdentityColumnName'; 
    
  • 波格丹Bodanov解決方案,使用try/catch也可以工作,但是額外的檢查應該將異常處理限制在IDENTITY_INSERT is already ON for table 'MyTable'. Cannot perform SET operation for table 'MyTable';

5

如果您試圖關閉某個其他表的IDENTITY_INSERT以避免在設置IDENTITY_INSERT時出現錯誤,則以下內容也適用於您。正如其他人對此線程所說的,IDENTITY_INSERT是一個沒有直接可見性的會話設置。不過,我做了一個有趣的發現,即SET IDENTITY_INSERT OFF對於任何具有IDENTITY_INSERT爲該表的IDENTITY_INSERT爲ON的表都不會出錯。因此,我想我可以在數據庫中爲每個具有標識的表調用SET IDENTITY_INSERT ... OFF。這感覺有點像一個蠻力的解決方案,但 我發現下面的動態SQL塊很好地做了這個技巧。

---- make sure IDENTITY_INSERT is OFF ---- 
DECLARE @cmd NVARCHAR(MAX) 
SET @cmd = CAST((SELECT 'SET IDENTITY_INSERT ' + 
      QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' + 
      QUOTENAME(t.name) + ' OFF' + CHAR(10) 
      FROM sys.columns c 
      JOIN sys.tables t ON t.object_id = c.object_id 
      WHERE c.is_identity = 1 
      ORDER BY 1 FOR XML PATH('')) AS NVARCHAR(MAX)) 
EXEC sp_executesql @cmd 
2

您可以發現identity_insert是否開啓,如果是,以及使用下面的代碼是什麼表。

declare @tableWithIdentity varchar(max) = ''; 
SET IDENTITY_INSERT ExampleTable ON 

begin try 
    create table #identityCheck (id int identity(1,1)) 
    SET IDENTITY_INSERT #identityCheck ON 
    drop table #identityCheck 
end try 
begin catch 
    declare @msg varchar(max) = error_message() 
    set @tableWithIdentity= @msg; 
    set @tableWithIdentity = 
    SUBSTRING(@tableWithIdentity,charindex('''',@tableWithIdentity,1)+1, 10000) 

    set @tableWithIdentity = SUBSTRING(@tableWithIdentity,1, charindex('''',@tableWithIdentity,1)-1) 

    print @msg; 
    drop table #identityCheck 
end catch 

if @tableWithIdentity<>'' 
begin 
    print ('Name of table with Identity_Insert set to ON: ' + @tableWithIdentity) 
end 
else 
begin 
    print 'No table currently has Identity Insert Set to ON' 
end 
+0

好戲法,試着抓住 – Graeme

+1

@Graeme:謝謝,我認爲這個問題的實際答案可能是有用的,這是我知道這樣做的唯一方法。 – jmoreno

相關問題