SCOPE_IDENTITY () dla identyfikatorów GUID?

94

Czy ktoś może mi powiedzieć, czy istnieje odpowiednik SCOPE_IDENTITY()używania identyfikatorów GUID jako klucza podstawowego w programie SQL Server?

Nie chcę najpierw tworzyć identyfikatora GUID i zapisywać go jako zmienną, ponieważ używamy sekwencyjnych identyfikatorów GUID jako naszych kluczy podstawowych.

Masz pomysł na najlepszy sposób na pobranie ostatnio wstawionego klucza podstawowego GUID?

bplus
źródło

Odpowiedzi:

100

Możesz odzyskać GUID za pomocą OUTPUT. Działa to również wtedy, gdy wstawiasz wiele rekordów.

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

Odniesienie: Eksploracja klauzuli OUTPUT języka SQL 2005

Rob Garrison
źródło
2
Jak wspomina anishmarokey, powinieneś używać NewSequentialID () do generowania swoich identyfikatorów GUID, a nie NewID ().
Rob Garrison
1
@RobGarrison Imo, GUID jako PK jest naprawdę korzystny tylko w stosunku do int / bigint w systemach rozproszonych. Jeśli trafiasz do bazy danych, aby pobrać identyfikator, równie dobrze możesz użyć int / bigint. NewSequentialID () może być używane tylko jako domyślne ograniczenie (na przykład nie można jawnie wstawiać za pomocą NewSequentialID ()). Jako takie, myślę, że większość scenariuszy, gdzie można go używać należy robić rzeczy inaczej i tak.
Shiv
OUTPUTKlauzula daje błąd na każdym stole, który ma wyzwalacz insert dołączony.
Cobus Kruger
62

Nie ma odpowiednika SCOPE_IDENTITY () w przypadku używania identyfikatorów GUID jako kluczy podstawowych, ale można użyć klauzuli OUTPUT, aby osiągnąć podobny wynik. Nie musisz używać zmiennej tabeli do wyjścia.

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

GO

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

Powyższy przykład jest przydatny, jeśli chcesz odczytać wartość z klienta .Net. Aby odczytać wartość z .Net, wystarczy użyć metody ExecuteScalar.

...
string sql = "INSERT INTO GuidTest(IntColumn) OUTPUT inserted.GuidColumn VALUES(1)";
SqlCommand cmd = new SqlCommand(sql, conn);
Guid guid = (Guid)cmd.ExecuteScalar();
...
Daniel
źródło
9

chcesz użyć NEWID ()

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

    select @id

ale problem z indeksem klastrowym istnieje w identyfikatorze GUID. przeczytaj też ten NEWSEQUENTIALID () .To są moje pomysły, zastanów się, zanim użyjesz GUID jako głównego klucza . :)

anishMarokey
źródło
10
„Funkcja wbudowana newsequentialid () może być używana tylko w wyrażeniu DEFAULT dla kolumny typu„ uniqueidentifier ”w instrukcji CREATE TABLE lub ALTER TABLE. Nie można jej łączyć z innymi operatorami w celu utworzenia złożonego wyrażenia skalarnego.
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
źródło
2

Używając tego wątku jako zasobu, utworzyłem następujące elementy do użycia w wyzwalaczu:

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;

Może pomóc komuś innemu zrobić to samo. Ciekawe, czy ktoś ma do powiedzenia coś złego pod względem wydajności, czy to nie jest dobry pomysł, czy nie.

TravisWhidden
źródło
po ponownym przeczytaniu pytania zdałem sobie sprawę, że to naprawdę nie odpowiada na pytanie użytkowników ... ale nadal może być pomocne dla kogoś, ponieważ podobne odpowiedzi są tego samego typu.
TravisWhidden