这是我正在查看的表的简化版本:
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
INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField) SELECT NEWSEQUENTIALID() as Id, '6/25/2015' as SecondField, 'Example' as ThirdField
这失败并显示错误
newsequentialid()内置函数只能在CREATE TABLE或ALTER TABLE语句中的’uniqueidentifier’类型的列的DEFAULT表达式中使用。它不能与其他运算符组合以形成复杂的标量表达式。
INSERT INTO [dbo].[FrustratingTable] (SecondField,ThirdField) SELECT '6/25/2015' as SecondField, 'Example' as ThirdField
失败并显示错误
无法将值NULL插入表“ mydatabase.dbo.frustratingtable”的列“ id”中;列不允许为空。INSERT失败。
是否可以在不更改表定义的情况下解决此问题?
您可以通过使用表变量来执行此操作:
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
由于table变量通过a设置值default,因此我们可以使用NEWSEQUENTIALID()。
default
NEWSEQUENTIALID()
当然,对于非常大的数据集,暂时隐藏两个数据副本是有代价的。
一种替代方法是使用一个较旧的解决方案,称为COMB,该解决方案在NEWSEQUENTIALID()引入之前就已经使用过:
SELECT CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
生成uniqueidentifiers比NEWID()其本身具有更好的局部性。
uniqueidentifiers
NEWID()