GUIDs的SCOPE_IDENTITY()用法?

104

当使用GUID作为SQL Server中的主键时,是否有类似于SCOPE_IDENTITY()的等效方法?

由于我们正在使用顺序GUID作为我们的主键,因此不想先创建GUID并保存为变量。

有什么最好的方法来检索最后插入的GUID主键吗?

5个回答

104

你可以使用 OUTPUT 来获取 GUID,在插入多条记录时同样适用。

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

参考资料: 了解SQL 2005的OUTPUT子句


3
如anishmarokey所提到的,你应该使用NewSequentialID()来生成GUID,而不是NewID()。 - Rob Garrison
1
@RobGarrison 在我看来,GUID作为主键只在分布式系统中比int/bigint更有优势。如果您需要访问数据库以获取ID,那么最好使用int/bigint。NewSequentialID()只能用作默认约束(例如,您不能显式地使用NewSequentialID()插入)。因此,在大多数情况下,您可以使用它时,您应该以不同的方式处理事情。 - Shiv
OUTPUT 子句会在任何附有插入触发器的表上产生错误。 - Cobus Kruger

69

使用GUID作为主键时,没有像SCOPE_IDENTITY()一样的等效函数,但您可以使用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 用作主键之前进行思考。 :)


12
"newsequentialid() 内置函数只能在 CREATE TABLE 或 ALTER TABLE 语句中,针对一个 'uniqueidentifier' 类型的列的 DEFAULT 表达式中使用。 它不能与其他运算符组合形成复杂的标量表达式。" - 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;

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接