【问题标题】:SCOPE_IDENTITY() for GUIDs?GUID 的 SCOPE_IDENTITY() ?
【发布时间】:2010-12-03 08:32:18
【问题描述】:

谁能告诉我在 SQL Server 中使用 GUID 作为主键时是否有 SCOPE_IDENTITY() 的等效项?

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

知道检索最后插入的 GUID 主键的最佳方法是什么吗?

【问题讨论】:

    标签: sql sql-server guid uniqueidentifier scope-identity


    【解决方案1】:

    您可以使用 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
    

    参考:Exploring SQL 2005’s OUTPUT Clause

    【讨论】:

    • 正如 anishmarokey 提到的,您应该使用 NewSequentialID() 来生成您的 GUID,而不是 NewID()。
    • @RobGarrison Imo,GUID 作为 PK 仅在分布式系统中优于 int/bigint。如果您要访问数据库以获取 ID,则不妨使用 int/bigint。 NewSequentialID() 只能用作默认约束(例如,您不能使用 NewSequentialID() 显式插入)。因此,我认为在您可以使用它的绝大多数情况下,无论如何您都应该以不同的方式做事。
    • OUTPUT 子句在任何附加了插入触发器的表上都会出错。
    【解决方案2】:

    使用 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();
    ...
    

    【讨论】:

      【解决方案3】:

      你想使用 NEWID()

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

      但是 GUID 中存在聚集索引问题。也读过这个NEWSEQUENTIALID()。这些是我的想法,在使用 GUID 作为primary Key 之前想一想。 :)

      【讨论】:

      • "newsequentialid() 内置函数只能用于 CREATE TABLE 或 ALTER TABLE 语句中“uniqueidentifier”类型列的 DEFAULT 表达式。不能与其他运算符组合使用形成一个复杂的标量表达式。”
      【解决方案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;
      

      【讨论】:

        【解决方案5】:

        将此线程用作资源,我创建了以下内容以在触发器中使用:

        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;
        

        可能会帮助其他人做同样的事情。好奇如果这不是一个好主意,是否有人有什么不好的说法。

        【讨论】:

        • 重新阅读问题后,我意识到这确实不能回答用户的问题......但仍然可能对某人有所帮助,因为类似的答案是相同类型的响应。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多