SCOPE_IDENTITY () für GUIDs?

94

Kann mir jemand sagen, ob es ein Äquivalent zur SCOPE_IDENTITY()Verwendung von GUIDs als Primärschlüssel in SQL Server gibt?

Ich möchte nicht zuerst die GUID erstellen und als Variable speichern, da wir sequentielle GUIDs als Primärschlüssel verwenden.

Haben Sie eine Idee, wie Sie den zuletzt eingefügten GUID-Primärschlüssel am besten abrufen können?

bplus
quelle

Antworten:

98

Sie können die GUID mithilfe von OUTPUT zurückerhalten. Dies funktioniert auch, wenn Sie mehrere Datensätze einfügen.

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

Referenz: Erkunden der OUTPUT-Klausel von SQL 2005

Rob Garrison
quelle
2
Wie anishmarokey erwähnt, sollten Sie NewSequentialID () verwenden, um Ihre GUIDs zu generieren, und nicht NewID ().
Rob Garrison
@RobGarrison Imo, GUID als PK ist nur in verteilten Systemen gegenüber int / bigint wirklich vorteilhaft. Wenn Sie die Datenbank zum Abrufen einer ID drücken, können Sie auch int / bigint verwenden. NewSequentialID () kann nur als Standardeinschränkung verwendet werden (Sie können beispielsweise nicht explizit mit NewSequentialID () einfügen). Als solche, ich glaube , die große Mehrheit der Szenarien , in denen Sie können es verwenden Sie die Dinge anders machen sowieso werden sollte.
Shiv
Die OUTPUTKlausel gibt einen Fehler für jede Tabelle aus, an die ein Einfügetrigger angehängt ist.
Cobus Kruger
60

Es gibt kein SCOPE_IDENTITY () -Äquivalent, wenn GUIDs als Primärschlüssel verwendet werden. Sie können jedoch die OUTPUT-Klausel verwenden, um ein ähnliches Ergebnis zu erzielen. Sie müssen keine Tabellenvariable für die Ausgabe verwenden.

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

GO

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

Das obige Beispiel ist nützlich, wenn Sie den Wert von einem .NET-Client lesen möchten. Um den Wert aus .Net zu lesen, verwenden Sie einfach die ExecuteScalar-Methode.

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

Sie möchten NEWID () verwenden

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

    select @id

Clustered-Index-Probleme gibt es jedoch in der GUID. Lesen Sie auch diese NEWSEQUENTIALID (). Dies sind meine Ideen. Denken Sie nach, bevor Sie die GUID als Primärschlüssel verwenden . :) :)

anishMarokey
quelle
10
"Die integrierte Funktion newsequentialid () kann nur in einem DEFAULT-Ausdruck für eine Spalte vom Typ 'uniqueidentifier' in einer Anweisung CREATE TABLE oder ALTER TABLE verwendet werden. Sie kann nicht mit anderen Operatoren kombiniert werden, um einen komplexen skalaren Ausdruck zu bilden."
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
quelle
2

Mit diesem Thread als Ressource habe ich Folgendes zur Verwendung in einem Trigger erstellt:

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;

Könnte jemand anderem helfen, dasselbe zu tun. Neugierig, ob jemand etwas Schlechtes zu sagen hat, wenn dies keine gute Idee ist oder nicht.

TravisWhidden
quelle
Nachdem ich die Frage erneut gelesen hatte, stellte ich fest, dass dies die Frage des Benutzers wirklich nicht beantwortet ... aber dennoch für jemanden hilfreich sein könnte, da die ähnlichen Antworten dieselbe Art von Antwort sind.
TravisWhidden