92 votes

Comment vérifier si IDENTITY_INSERT est réglé sur ON ou OFF dans SQL Server ?

Je l'ai cherché, mais les fils de discussion dans lesquels il apparaissait avaient tendance à avoir des réponses de personnes qui ne comprenaient pas la question.

Prenez la syntaxe suivante :

SET IDENTITY_INSERT Table1 ON

Comment faire quelque chose de plus comme ça :

GET IDENTITY_INSERT Table1

Je ne veux pas faire quoi que ce soit aux données de la base de données ou aux paramètres pour obtenir cette information. Merci !

5 votes

Il est amusant de constater que vous avez mentionné que les gens comprennent mal la question et que la grande majorité des réponses ici font exactement cela.

4 votes

Pour vous et les autres personnes qui se renseignent sur le sujet, la vraie question est la suivante : sessions . Vous ne voudrez probablement vérifier/restaurer la valeur d'IDENTITY_INSERT que pour un fichier de type session suffisamment long et compliqué pour permettre, puis empêcher, les insertions d'identité. (Une étape de travail en continu ?) PARCE QUE si vous démarrez une nouvelle session, IDENTITY_INSERT est éteint ! Si vous n'êtes pas sûr que quelque chose reste la même session, sessions google (pas exactement = connexions), consultez sys.dm_exec_sessions y sys.dm_exec_connections ou télécharger sp_WhoIsActive y EXEC sp_WhoIsActive @show_sleeping_spids = 2, @show_own_spid = 1

41voto

Noobgrammer Points 891

Depuis SET IDENTITY_INSERT est sensible à la session, il est géré au niveau du tampon sans être stocké quelque part. Cela signifie que nous n'avons pas besoin de vérifier le IDENTITY_INSERT car nous n'utilisons jamais ce mot clé dans la session actuelle.

Désolé, je ne peux pas vous aider.

Bonne question cependant :)

Fuente: Ici

Mise à jour Il existe peut-être des moyens de le faire, comme le montre le site que j'ai mis en lien, mais, selon moi, cela demande trop d'efforts pour être 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 votes

Merci. Je viens d'apprendre son existence hier, donc je ne suis pas vraiment sûr de savoir comment appliquer ce que vous dites. En fait, nous avons deux bases de données sur deux serveurs différents, et arrêter l'une ou l'autre et la redémarrer va être un problème. La session à laquelle vous faites référence dure-t-elle plus de quelques minutes si le service de base de données est laissé en marche indéfiniment ? En fait, j'ai défini la valeur plusieurs fois sur l'une des bases de données sans prendre de notes au préalable, et je dois m'assurer que toute modification de ce type est annulée.

1 votes

Notez que ceci n'est pas une réponse de ma part, mais de ma source à social.msdn.microsoft.com/Forums/fr/transactsql/thread/ (forums officiels de Microsoft, j'en ai des tonnes dans mes favoris.) Tout dépend des performances de ces serveurs. Evidemment, si les serveurs sont lents/les services concernant le serveur SQL s'arrêtent, ce code (en pseudo ici) ne fonctionnera pas bien. Pourquoi avez-vous besoin de connaître l'état d'identité des tables ? Si le service fonctionne indéfiniment, cette session ne devrait pas durer longtemps (en fonction des spécifications du serveur et de la taille des tables)...

1 votes

J'essaie simplement de remettre la base de données dans l'état où elle était avant que je ne commence à jouer avec les valeurs IDENTITY_INSERT.

22voto

Lo Sauer Points 5469

En résumé :

  • La solution de Nathan est le plus rapide :

    SELECT OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity');
    • en utilisant un wrapper API, on peut réduire l'ensemble de la vérification à la seule vérification des rangs. Par exemple, lorsque l'on utilise l'API C# SqlDataReaders propriété HasRows et une construction de requête comme :

      SELECT CASE OBJECTPROPERTY(OBJECT_ID('MyTable'), 'TableHasIdentity')
             WHEN 1 THEN '1' ELSE NULL END
  • La solution de Ricardo permet plus de flexibilité mais requiert le nom d'identité de la colonne

    SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('MyTable', 'U') 
                            AND name = 'MyTableIdentityColumnName';
  • Solution de Bogdan Bodanov, utilisant try / catch fonctionnerait aussi bien, mais une vérification supplémentaire devrait limiter le traitement des exceptions aux cas de IDENTITY_INSERT is already ON for table 'MyTable'. Cannot perform SET operation for table 'MyTable';

8 votes

Les non-solutions ne peuvent pas être les plus rapides - ni les solutions de Nathan ni celles de Ricardo ne traitent réellement le problème. Elles testent si une colonne d'identité existe, et non si IDENTITY_INSERT est activé ou désactivé pour cette colonne dans la session actuelle.

7voto

Mike Stankavich Points 71

Si vous essayez de désactiver IDENTITY_INSERT pour une autre table afin d'éviter d'obtenir une erreur lorsque vous souhaitez activer IDENTITY_INSERT, la méthode suivante peut également vous convenir. Comme d'autres l'ont dit dans ce fil de discussion, IDENTITY_INSERT est un paramètre de session sans visibilité directe. Cependant, j'ai fait une découverte intéressante : SET IDENTITY_INSERT OFF n'entraîne pas d'erreur pour une table ayant une identité, que IDENTITY_INSERT soit ON ou non pour cette table. Il m'est donc apparu que je pouvais simplement appeler SET IDENTITY_INSERT ... OFF pour chaque table ayant une identité dans la base de données. Cela ressemble un peu à une solution de force brute, mais j'ai trouvé que le bloc SQL dynamique suivant faisait très bien l'affaire.

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

0 votes

Ce es une solution de force brute. Et je ne vois humblement pas dans quels scénarios elle serait à la fois nécessaire et sûre. Si un appel à set IDENTITY_INSERT on a été faite dans le script appelant (ou avant), il y a très certainement une raison pour cela. :p Supposer que l'appelant ne continuera pas à se fier à l'information par la suite est faux et potentiellement dangereux. Du point de vue de la conception, il serait préférable, à mon avis, d'essayer de l'activer quand même et de laisser l'ensemble s'écraser et brûler s'il le faut. Au moins, les développeurs auront une idée de ce qui s'est mal passé - en supposant que les erreurs sont enregistrées quelque part.

0 votes

Ceci étant dit, je ne voterai pas parce que je continue à penser que votre réponse peut être utile pour quelqu'un qui travaille sur une application pour résoudre les problèmes liés à la DB. Mais c'est vraiment le seul scénario auquel je peux penser. Bien sûr, n'hésitez pas à me dire si je manque quelque chose :)

1voto

Ricardo Points 59

Si vous voulez connaître la variable de session... Bonne question, mais je ne vois pas où cette information pourrait être utile. En exécution normale pour vérifier la réponse d'une table normale à une insertion, cela devrait fonctionner !

-- Si vous voulez seulement savoir s'il y a une insertion d'identité sur une table donnée :

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

-- Ou... Utilisez ceci si vous voulez exécuter quelque chose en fonction du résultat :

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

Amusez-vous bien !

9 votes

Cela passe à côté de l'essentiel, la question est de savoir si IDENTITY_INSERT n'est pas activé si la table a une colonne d'identité

3 votes

is_identity dans la colonne sys.columns identifie si cette colonne est une colonne d'identité ou non, et non pas si la variable IDENTITY_INSERT es ON o OFF

-1voto

Nathan Tregillus Points 1450

Vous pouvez également utiliser la méthode ObjectProperty pour déterminer si une table a une 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

0 votes

Merci mon ami. C'est ce que j'avais cherché

3 votes

Je suis désolé mais cela ne répond pas à la question. Cela va vérifier l'état de TableHasIdentity comme défini dans le tableau, no la session réelle stockée IDENTITY_INSERT qui est ce que l'op recherche. Essayez vous-même : créez une requête qui vérifie la propriété, puis modifiez la valeur de la propriété. IDENTITY_INSERT pour le tableau, puis récupérer à nouveau la propriété de l'objet. Sa valeur sera toujours la même qu'avant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X