如何插入使用顺序GUID作为主键的表?

时间:2015-06-26 12:39:06

标签: sql sql-server-2012 guid

以下是我正在查看的表格的简化版本:

CREATE TABLE [dbo].[FrustratingTable]
(
    [Id] Uniqueidentifier NOT NULL
    , [SecondField] [datetime]
    , [ThirdField] varchar(128)
)

我想在此表中插入新记录。我尝试了3种方法:

INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
    SELECT newid() as Id, 
           '6/25/2015' as SecondField, 'Example' as ThirdField

这种方法会插入,但生成的键不是一个很好的顺序GUID,就像表中的其他GUID一样

INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
SELECT NEWSEQUENTIALID() as Id, '6/25/2015' as SecondField, 'Example' as ThirdField

失败,错误

  

newsequentialid()内置函数只能在DEFAULT表达式中用于" uniqueidentifier'在CREATE TABLE或ALTER TABLE语句中。它不能与其他运算符组合以形成复杂的标量表达式。

INSERT INTO [dbo].[FrustratingTable] (SecondField,ThirdField)
SELECT '6/25/2015' as SecondField, 'Example' as ThirdField

此操作失败并显示错误

  

无法将值NULL插入列' id',table' mydatabase.dbo.frustratingtable&#39 ;;列不允许空值。 INSERT失败。

是否可以在不改变表定义的情况下解决这个问题?

3 个答案:

答案 0 :(得分:14)

您可以通过使用表变量来实现此目的:

declare @t table (
    ID uniqueidentifier not null default newsequentialid(),
    SecondField datetime,
    ThirdField varchar(128)
)
insert into @t (SecondField,ThirdField)
    output inserted.ID,inserted.SecondField,inserted.ThirdField
    into FrustratingTable
values
('20150101','abc'),
('20150201','def'),
('20150301','ghi')

select * from FrustratingTable

结果:

Id                                   SecondField             ThirdField
------------------------------------ ----------------------- ------------
1FEBA239-091C-E511-9B2F-78ACC0C2596E 2015-01-01 00:00:00.000 abc
20EBA239-091C-E511-9B2F-78ACC0C2596E 2015-02-01 00:00:00.000 def
21EBA239-091C-E511-9B2F-78ACC0C2596E 2015-03-01 00:00:00.000 ghi

由于表变量通过default设置值,我们可以使用NEWSEQUENTIALID()

当然,对于非常大的数据集,暂时有两个数据副本潜伏着会受到惩罚。

另一种方法是使用名为COMB的旧解决方案,该解决方案在引入NEWSEQUENTIALID()之前使用:

SELECT CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)

生成uniqueidentifiers的位置比NEWID()本身更好。

答案 1 :(得分:1)

好的,如果您首先从this answer获取[IncrementGuid]功能, 然后你可以做这样的事情,

Fiddle Here

INSERT [dbo].[FrustratingTable]
SELECT
      [dbo].[IncrementGuid](MAX([Id])),
      '01/01/01',
      '3'
  FROM
      [dbo].[FrustratingTable];

警告:

一旦你在另一个答案中审阅了这个功能,你就会同意,必须有一个更好的方法。

更改需要GUID顺序的代码。

答案 2 :(得分:0)

ALTER TABLE FrustratingTable
ALTER COLUMN id uniqueidentifier not null default newsequentialid()