SCOPE_IDENTITY () para GUID?

94

¿Alguien puede decirme si hay un equivalente de SCOPE_IDENTITY()cuando se usan GUID como clave principal en SQL Server?

No quiero crear el GUID primero y guardarlo como una variable, ya que estamos usando GUID secuenciales como nuestras claves principales.

¿Alguna idea de cuál es la mejor manera de recuperar la última clave primaria GUID insertada?

bplus
fuente

Respuestas:

98

Puede recuperar el GUID utilizando OUTPUT. Esto también funciona cuando está insertando varios registros.

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

Referencia: Exploración de la cláusula OUTPUT de SQL 2005

Rob Garrison
fuente
2
Como menciona anishmarokey, debe usar NewSequentialID () para generar sus GUID y no NewID ().
Rob Garrison
@RobGarrison Imo, GUID como PK solo es realmente ventajoso sobre int / bigint en sistemas distribuidos. Si está presionando la base de datos para obtener una identificación, también puede usar int / bigint. NewSequentialID () solo se puede usar como una restricción predeterminada (no puede insertar explícitamente usando NewSequentialID () por ejemplo). Como tal, creo que la gran mayoría de escenarios en los que puedes usarlo deberías estar haciendo las cosas de manera diferente de todos modos.
Shiv
La OUTPUTcláusula da un error en cualquier tabla que tenga adjunto un activador de inserción.
Cobus Kruger
60

No hay equivalente de SCOPE_IDENTITY () cuando se usan GUID como claves principales, pero puede usar la cláusula OUTPUT para lograr un resultado similar. No es necesario utilizar una variable de tabla para la salida.

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

GO

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

El ejemplo anterior es útil si desea leer el valor de un cliente .Net. Para leer el valor de .Net, simplemente use el método ExecuteScalar.

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

quieres usar NEWID ()

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

    select @id

pero el problema del índice agrupado está en GUID. lea este también NEWSEQUENTIALID () . Estas son mis ideas, piense antes de usar GUID como clave principal . :)

anishMarokey
fuente
10
"La función incorporada newsequentialid () solo se puede usar en una expresión DEFAULT para una columna de tipo 'identificador único' en una instrucción CREATE TABLE o ALTER TABLE. No se puede combinar con otros operadores para formar una expresión escalar compleja".
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
fuente
2

Usando este hilo como recurso, creé lo siguiente para usar dentro de un disparador:

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;

Podría ayudar a otra persona a hacer lo mismo. Es curioso si alguien tiene algo malo que decir en cuanto al rendimiento si esto no es una buena idea o no.

TravisWhidden
fuente
después de volver a leer la pregunta, me di cuenta de que esto realmente no responde a la pregunta de los usuarios ... pero aún así podría ser útil para alguien porque las respuestas similares son el mismo tipo de respuesta.
TravisWhidden