SCOPE_IDENTITY () pour les GUID?

94

Quelqu'un peut-il me dire s'il existe un équivalent de l' SCOPE_IDENTITY()utilisation de GUID comme clé primaire dans SQL Server?

Je ne veux pas créer le GUID en premier et l'enregistrer en tant que variable car nous utilisons des GUID séquentiels comme clés primaires.

Une idée de la meilleure façon de récupérer la dernière clé primaire GUID insérée?

bplus
la source

Réponses:

98

Vous pouvez récupérer le GUID en utilisant OUTPUT. Cela fonctionne également lorsque vous insérez plusieurs enregistrements.

CREATE TABLE dbo.GuidPk (
    ColGuid uniqueidentifier NOT NULL DEFAULT NewSequentialID(),
    Col2    int              NOT NULL
)
GO

DECLARE @op TABLE (
    ColGuid uniqueidentifier
)

INSERT INTO dbo.GuidPk (
    Col2
)
OUTPUT inserted.ColGuid
INTO @op
VALUES (1)

SELECT * FROM @op

SELECT * FROM dbo.GuidPk

Référence: Exploration de la clause OUTPUT de SQL 2005

Rob Garrison
la source
2
Comme le mentionne anishmarokey, vous devez utiliser NewSequentialID () pour générer vos GUID et non NewID ().
Rob Garrison
@RobGarrison Imo, GUID en tant que PK n'est vraiment avantageux que sur int / bigint dans les systèmes distribués. Si vous frappez la base de données pour récupérer un ID, vous pouvez également utiliser int / bigint. NewSequentialID () ne peut être utilisé que comme contrainte par défaut (vous ne pouvez pas insérer explicitement en utilisant NewSequentialID () par exemple). En tant que tel, je pense que dans la grande majorité des scénarios où vous pouvez l' utiliser, vous devriez de toute façon faire les choses différemment.
Shiv
La OUTPUTclause donne une erreur sur toute table qui a un déclencheur d'insertion attaché.
Cobus Kruger
60

Il n'y a pas d'équivalent SCOPE_IDENTITY () lors de l'utilisation de GUID comme clés primaires, mais vous pouvez utiliser la clause OUTPUT pour obtenir un résultat similaire. Vous n'avez pas besoin d'utiliser une variable de table pour la sortie.

CREATE TABLE dbo.GuidTest (
    GuidColumn uniqueidentifier NOT NULL DEFAULT NewSequentialID(),
    IntColumn int NOT NULL
)

GO

INSERT INTO GuidTest(IntColumn)
OUTPUT inserted.GuidColumn
VALUES(1)

L'exemple ci-dessus est utile si vous souhaitez lire la valeur d'un client .Net. Pour lire la valeur de .Net, utilisez simplement la méthode ExecuteScalar.

...
string sql = "INSERT INTO GuidTest(IntColumn) OUTPUT inserted.GuidColumn VALUES(1)";
SqlCommand cmd = new SqlCommand(sql, conn);
Guid guid = (Guid)cmd.ExecuteScalar();
...
Daniel
la source
9

vous voulez utiliser NEWID ()

    declare @id uniqueidentifier
    set @id  = NEWID()
    INSERT INTO [dbo].[tbl1]
           ([id])
     VALUES
           (@id)

    select @id

mais le problème d'index cluster est là dans GUID. Lisez celui-ci aussi NEWSEQUENTIALID () . Ce sont mes idées, réfléchissez avant d'utiliser GUID comme clé primaire . :)

anishMarokey
la source
10
"La fonction intégrée newsequentialid () ne peut être utilisée que dans une expression DEFAULT pour une colonne de type 'uniqueidentifier' dans une instruction CREATE TABLE ou ALTER TABLE. Elle ne peut pas être combinée avec d'autres opérateurs pour former une expression scalaire complexe."
Scott Whitlock
4
CREATE TABLE TestTable(KEY uniqueidentifier, ID VARCHAR(100), Name VARCHAR(100), Value tinyint);
Declare @id uniqueidentifier ;  
DECLARE @TmpTable TABLE (KEY uniqueidentifier);     
INSERT INTO [dbo].[TestTable]
    ([ID], [Name], Value])           
    OUTPUT INSERTED.KEY INTO @TmpTable           
    VALUES(@ID, @Name, @Value);           
SELECT @uniqueidentifier = KEY FROM @TmpTable; 
DROP TABLE TestTable;
Joe
la source
2

En utilisant ce fil comme ressource, j'ai créé ce qui suit à utiliser dans un déclencheur:

DECLARE @nextId uniqueIdentifier;
DECLARE @tempTable TABLE(theKey uniqueIdentifier NOT NULL DEFAULT NewSequentialID(), b int);
INSERT INTO @tempTable (b) Values(@b);
SELECT @nextId = theKey from @tempTable;

Pourrait aider quelqu'un d'autre à faire la même chose. Curieux de savoir si quelqu'un a quelque chose de négatif à dire en termes de performances si ce n'est pas une bonne idée ou non.

TravisCaché
la source
après avoir relu la question, j'ai réalisé que cela ne répondait vraiment pas à la question des utilisateurs ... mais cela pourrait quand même être utile à quelqu'un parce que les réponses similaires sont le même type de réponse.
TravisWhidden