SCOPE_IDENTITY () для GUID?


94

Хто-небудь може сказати мені, чи існує еквівалент SCOPE_IDENTITY()використання GUID як первинного ключа в SQL Server?

Я не хочу спочатку створювати GUID і зберігати як змінну, оскільки ми використовуємо послідовні GUID як наші первинні ключі.

Будь-яка ідея щодо найкращого способу отримання останнього вставленого первинного ключа GUID?

Відповіді:


98

Ви можете повернути GUID, використовуючи OUTPUT. Це працює, коли ви також вставляєте кілька записів.

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

Довідково: Вивчення статті OUTPUT SQL 2005


2
Як зазначає anishmarokey, ви повинні використовувати NewSequentialID () для створення ваших GUID, а не NewID ().
Роб Гаррісон,

@RobGarrison Imo, GUID як PK насправді вигідніший за int / bigint у розподілених системах. Якщо ви натискаєте БД, щоб отримати ідентифікатор, ви можете також використовувати int / bigint. NewSequentialID () можна використовувати лише як обмеження за замовчуванням (наприклад, ви не можете явно вставити, використовуючи NewSequentialID ()). Таким чином, я вважаю, що переважна більшість сценаріїв, коли ви можете ним скористатися, все одно повинні робити все по-іншому.
Шив

OUTPUTПоложення дає помилку на будь-яку таблиці , яка має тригер вставки додається.
Кобус Крюгер

60

Немає еквівалента SCOPE_IDENTITY () при використанні GUID в якості первинних ключів, але ви можете використовувати речення OUTPUT, щоб досягти подібного результату. Вам не потрібно використовувати змінну таблиці для виводу.

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

GO

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

Наведений вище приклад корисний, якщо ви хочете прочитати значення з клієнта .Net. Щоб прочитати значення з .Net, ви просто використовуєте метод ExecuteScalar.

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

9

ви хочете використовувати NEWID ()

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

    select @id

але проблема кластерного індексу є в GUID. прочитайте і цей NEWSEQUENTIALID () . Це мої ідеї, подумайте, перш ніж використовувати GUID як первинний ключ . :)


10
"Вбудовану функцію newsequentialid () можна використовувати лише у виразі DEFAULT для стовпця типу 'uniqueidentifier' в операторі CREATE TABLE або ALTER TABLE. Її не можна поєднувати з іншими операторами, щоб утворити складний скалярний вираз."
Скотт Уітлок

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;

2

Використовуючи цей потік як ресурс, я створив наступне для використання в рамках тригера:

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;

Може допомогти комусь іншому зробити те саме. Цікаво, чи є у когось щось погане, щоб сказати, мудрість, якщо це погана ідея чи ні.


перечитавши запитання, я зрозумів, що це насправді не відповідає на запитання користувачів ... але все одно може бути корисним для когось, оскільки подібні відповіді є тим самим типом відповіді.
TravisWhidden
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.