2012-05-17 6 views
51

Ho cercato questo, ma i thread in cui appariva tendevano ad avere risposte da persone che non capivano la domanda.Come si controlla se IDENTITY_INSERT è impostato su ON o OFF in SQL Server?

Prendere la seguente sintassi:

SET IDENTITY_INSERT Table1 ON 

Come si fa a fare qualcosa di più simile a questo:

GET IDENTITY_INSERT Table1 

Non voglio fare niente a che i dati nel database o per la impostazioni per ottenere queste informazioni. Grazie!

+2

Divertente come hai menzionato la gente fraintendendo la domanda e la stragrande maggioranza delle risposte qui facendo esattamente questo. – Fishcake

+2

Per te e altri su Google, la vera domanda: * sessioni *. Probabilmente vorresti solo controllare/ripristinare il valore di IDENTITY_INSERT per una * sessione * lunga e abbastanza complicata da consentire e successivamente impedire l'inserimento di identità. (Un passaggio di lavoro in esecuzione continua?) PERCHÉ se inizi una nuova sessione, 'IDENTITY_INSERT' è disattivato! Se non sei chiaro se qualcosa rimane la stessa sessione, sessioni di google (non esattamente = connessioni), controlla 'sys.dm_exec_sessions' e' sys.dm_exec_connections', o scarica 'sp_WhoIsActive' e' EXEC sp_WhoIsActive @show_sleeping_spids = 2, @show_own_spid = 1' –

risposta

25

Poiché SET IDENTITY_INSERT è sensibile alla sessione, è gestito a livello di buffer senza archiviare da qualche parte. Ciò significa che non è necessario verificare lo stato IDENTITY_INSERT poiché non usiamo mai questa parola chiave nella sessione corrente.

Spiacente, nessun aiuto per questo.

grande domanda però :)

Fonte: Here

Aggiornamento Ci sono modi forse per fare questo, visto anche nel sito che ho linkato, IMO, è troppo sforzo per essere utile .

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

Grazie. Ho appena saputo che esiste ieri, quindi non sono sicuro di come applicare ciò che stai dicendo. Fondamentalmente abbiamo due database su due server diversi, e chiuderne uno e riavviarlo sarà un problema. La sessione a cui ti riferisci dura più di un paio di minuti se il servizio di database viene lasciato in esecuzione indefinitamente? Fondamentalmente ho impostato il valore alcune volte su uno dei database senza prendere appunti in anticipo, e ho bisogno di fare in modo che ogni cambiamento come quello viene ripristinato. – Panzercrisis

+1

Nota che questa non è una mia risposta, ma dalla mia fonte su http://social.msdn.microsoft.com/Forums/en/transactsql/thread/1a6ba2bb-5e82-47e8-a1a0-16fc044b951e (forum Microsoft ufficiali , hanno tonnellate di quelli contrassegnati.) Tutto dipende dalle prestazioni su questi server. Ovviamente, se i server sono lenti/i servizi relativi a SQL Server si stanno spegnendo, questo codice (in pseudo qui) non funzionerà correttamente. Perché hai esattamente bisogno di conoscere lo stato di identità delle tabelle? Se il servizio viene eseguito a tempo indeterminato, questa sessione non dovrebbe durare a lungo (in base alle specifiche del server e alle dimensioni della tabella) ... – Eon

+0

Sto solo cercando di ripristinare il database nel modo in cui era prima che iniziassi a fare scherzi con i valori IDENTITY_INSERT . – Panzercrisis

3

Se si desidera conoscere la variabile di sessione ... Buona domanda, ma non riesco a capire dove questa informazione sarebbe utile. In normale esecuzione per controllare una normale risposta della tabella a un inserto, questo dovrebbe funzionare!

- Se si desidera solo sapere se c'è inserimento di identità su una determinata tabella:

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

- Oppure ... utilizzare questo se si desidera eseguire qualcosa a seconda del risultato:

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 

Buon divertimento!

+5

Manca il punto, la domanda riguarda se 'IDENTITY_INSERT' è attivo non se la tabella ha una colonna di identità – Fishcake

+0

La colonna 'is_identity' nella tabella' sys.columns' identifica se quella colonna è una colonna di identità o meno, non se la variabile 'IDENTITY_INSERT' è' ON' o 'OFF' –

0

è anche possibile utilizzare il metodo ObjectProperty per determinare se una tabella ha un'identità:

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

Molto buona domanda. Ho lo stesso problema. Potresti provare a reimpostare IDENTITY_INSERT utilizzando TRY/CATCH? Ad esempio, si crea il lavoro ma non si è certi che il lavoro sia finito e IDENTITY_INSERT sia impostato su OFF.

Perché non provate:

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

Anche io non sono sicuro che questo sta funzionando correttamente, ma vedo che l'aggiunta di solo SET IDENTITY_INSERT ... OFF non ha prodotto l'errore. Quindi è possibile impostare nel caso in cui alla fine SET IDENTITY_INSERT ... OFF.

12

In sintesi: soluzione

  • di Nathan è il più veloce:

    SELECT OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity'); 
    
    • quando si utilizza un involucro API, si può ridurre l'intero controllo di solo controllo per le righe. Per esempio quando si utilizza C# 's SqlDataReaders proprietà HasRows e una query costruire come:

      SELECT CASE OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity') 
           WHEN 1 THEN '1' ELSE NULL END 
      
  • soluzione di Ricardo consente una maggiore flessibilità, ma richiede nome di identità della colonna

    soluzione
    SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('MyTable', 'U') 
             AND name = 'MyTableIdentityColumnName'; 
    
  • Bogdan Bodanov, utilizzando try/catch funzionerebbe anche, ma il controllo aggiuntivo dovrebbe limitare la gestione delle eccezioni ai casi di IDENTITY_INSERT is already ON for table 'MyTable'. Cannot perform SET operation for table 'MyTable';

5

Se si sta tentando di disattivare IDENTITY_INSERT per qualche altra tabella per evitare di ricevere un errore quando si desidera impostare IDENTITY_INSERT, il seguente potrebbe funzionare anche per te. Come altri hanno detto su questo thread, IDENTITY_INSERT è un'impostazione di sessione senza visibilità diretta. Tuttavia, ho fatto la scoperta interessante che SET IDENTITY_INSERT OFF non genera errori per qualsiasi tabella che ha un'identità indipendentemente dal fatto che IDENTITY_INSERT sia ON per quella tabella. Quindi mi è venuto in mente che potevo semplicemente chiamare SET IDENTITY_INSERT ... OFF per ogni tabella con un'identità nel database. Mi sembra un po 'come una soluzione di forza bruta, ma ho trovato che il seguente blocco dinamico SQL ha fatto molto bene il trucco .

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

È possibile scoprire se identity_insert è attivo e, in caso affermativo, per quale tabella si utilizza il codice riportato di seguito.

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

bel trucco con try-catch – Graeme

+1

@Graeme: grazie, ho pensato che una risposta effettiva alla domanda potrebbe essere utile ed è l'unico modo che conosco per farlo. – jmoreno