Articles / Nouvelle technologies


Lorsqu'on utilise un compteur dans SQL Server pour gérer l'auto incrémentation d'un champ (IDENTITY) on a souvent la problématique suivante : comment récupérer la valeur du champs auto incrémenté lorque nous effectuons une insertion.

Nous avons plusieurs solutions :

  • SCOPE_IDENTITY
  • IDENT_CURRENT
  • @@IDENTITY

Face à un tel choix, dur de choisir... Pas tant que ça! Vous vous doutez bien que chaque solution à ses particularités.

IDENT_CURRENT renvoi bel et bien le dernier élément inséré. C'est d'ailleurs cette fonction qui donne la réponse la plus exacte mais qui ne nous intéressera pas dans ce cas-ci quand elle renvoi le dernier sans se soucier de la session et de l'étendue. Prenons un exemple pour voir où serait le problème :

Nous avons deux utilisateurs : X et Y. Ces deux utilisateurs font appel à une procédure stockée qui fait un INSERT et renvoi la valeur du champ auto incrémenté.

A l'instant T, nous avons donc deux exécution de notre procédure stockée qui nous appellerons : PROC A et PROC B. Dans un premier temps c'est PROC A qui prend la main et qui fait l'ajout. La valeur que devrait renvoyé la procédure stockée est "1" mais avant de faire IDENT_CURRENT(), PROC B prend la main (pas de chance hein?) et utilise donc le compteur qui à maintenant la valeur 2. PROC A reprend la main et arrive à IDENT_CURRENT() qui renvoi... 2 alors qu'on voudrai bien avoir en valeur de retour 1. Problème tout aussi grave, lorsque PROC B prend la main pour terminer la procédure, elle renvoi, elle aussi, 2! On a bien la dernière valeur du compteur mais cela ne nous intéresse pas dans notre cas! On aurait aimé que PROC A renvoi 1 et PROC B -> 2. Notez que cela aurait pu se produire... ou pas, c'est ça le problème.

On voit souvent @@IDENTITY comme solution sur les forums et blogs. En effet, @@IDENTITY renvoi la valeur en tenant compte de la session. Ainsi, le cas de IDENT_CURRENT ne peut pas arriver avec @@IDENTITY. Malheureusement, il existe des situations un peu plus complexe où ne pourrions pas compter sur @@IDENTITY car celui-ci ne regarde pas à l'étendue de la requête. Je vous laisse imaginer le cas problématique où nous aurions deux champs auto incrémentés dans deux tables différentes mais directement liées par un déclencheur (lors de l'ajout dans T1, un déclencheur déclenche un ajout dans T2). Si le but de la procédure stockée est de renvoyé les deux valeurs des champs auto incrémentés, alors on risque d'avoir des valeurs assez nébuleuses.

Du coup, c'est SCOPE_IDENTITY qui convient le mieux dans notre cas car cette fonction prend en compte la session et l'étendue.

Pour résumer :

  • SCOPE_IDENTITY : prend en compte la table, l'étendue et la session
  • IDENT_CURRENT : prend en compte uniquement la table
  • @@IDENTITY : prend en compte la table et la session.
  • NB : Merci à Aurélien Verla qui m'a fait découvrir SCOPE_IDENTITY et sa nuance avec @@IDENTITY :-)



    Lire la suite...
    Tags:
    Catégorie : SQL Server | T-SQL

    Une question sur cet article? n'hésitez pas a me contacter par Live Messegner. Suis-je connecté?

    Soyez le premier à noter ce billet

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Par Loïc Bar le 02/04/2008 12:50:31

    Permalink | Commentaires (3) | Post RSS |


    Commentaires

    02/04/2008 22:06:31

    sebastien crocquesel

    Dans le même genre de problématique mais lorsqu'on insert N enregistrement en même temps. Cette fois SCOPE_IDENTITY, IDENT_CURRENT, @@IDENTITY ne nous aideront pas vraiment.
    Plutot que de passer par des triggers, une solution serait d'utiliser la clause OUTPUT.
    Ainsi, il faut déclarer une table
    DECLARE @matable (ID uniqueidentifier)
    puis faire l'insertion
    insert into foo(bar)
    OUTPUT inserted.ID into @matable
    select bar from foo2
    Et enfin de jouer avec nos nouveaux ids
    select * from @matable -- retourne les nouveaux identifiants




    sebastien crocquesel fr

    02/04/2008 22:39:19

    Alexandre Marlot

    Intéressant Smile
    Je me coucherai moins bete ! Je ne connaissais pas exactement la différence.

    Alexandre Marlot fr

    03/04/2008 11:05:26

    loicbar

    Merci Sebastien Smile. Pas mal comme solution. Faudra le traité dans un prochain article Laughing.

    loicbar be

    Ajouter un commentaire



    (Affichera votre icône Gravatar)  

      Country flag










    Propulsé par BlogEngine.NET, modifé par Loïc Bar.