回答

收藏

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

技术问答 技术问答 139 人阅读 | 0 人回复 | 2023-09-12

这是我正在查看的简化版表:1 p  f: Y. w  L* Z4 e
CREATE TABLE [dbo].[FrustratingTable](    [Id] Uniqueidentifier NOT NULL    ,[SecondField] [datetime]    ,[ThirdField] varchar(128))我想在这个表中插入新的记录。我尝试了三种方法:
2 q& g) h( s$ K7 Z* |INSERT INTO [dbo].[FrustratingTable] (Id,SecondField,ThirdField)    SELECT newid() as Id,   as SecondField,'Example' as ThirdField这种方法可以插入,但生成的键不同于表中的其他键,这不是一个很好的顺序GUID/ z2 M$ h6 E4 N8 u- Y1 t
INSERT INTO [dbo].[FrustratingTable] (Id,SecondField,ThirdField)SELECT NEWSEQUENTIALID() as Id,'6/25/2015' as SecondField,'Example' as ThirdField失败并显示错误0 w3 _6 N+ P% g. u2 T3 v
newsequentialid()内置函数只能在CREATE TABLE或ALTER
3 F5 o: z) T% W2 UTABLE语句中的’uniqueidentifier’类型的列的DEFAULT在表达式中使用。它不能与其他操作符相结合,形成复杂的标量表达式。" \# b5 [! O: ~" W
INSERT INTO [dbo].[FrustratingTable] (SecondField,ThirdField)SELECT as SecondField,'Example' as ThirdField失败并显示错误
- ]1 C/ z* J8 V' Q3 Q无法将值NULL插入表“ mydatabase.dbo.frustratingtable”的列“ id中;列不允许为空。INSERT失败。: l. j1 g& F) _/ x' d3 J6 l4 f
这个问题能在不改变表定义的情况下解决吗?( g* g+ s( I9 G; ]6 m3 i' l
                                                               
& \# Y* @& x7 G( D& }" L2 ~' s    解决方案:                                                               
+ X6 l, R& x$ s" }7 Y* u  Q* w/ @! l                                                                使用表变量可以执行此操作:
* N" T" i* s# K: {: Z* ?# ddeclare @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 FrustratingTablevalues('20150101','abcdefghi')select * from FrustratingTable结果:
$ {+ c$ s( O- M" A9 }" b$ h% wId                                   SecondField             ThirdField------------------------------------ ----------------------- ------------1FEBA239-091C-E511-9B2F-78ACC0C2596E 2015-01-01 00:00:00.000 abc20EBA239-091C-E511-9B2F-78ACC0C2596E 2015-02-01 00:00:00.000 def21EBA239-091C-E511-9B2F-78ACC0C2596E 2015-03-01 00:00:00.000 ghi由于table变量通过a设置值default,所以我们可以使用它NEWSEQUENTIALID()。
7 o; M2 D4 N4 m' r  H当然,对于非常大的数据集,暂时隐藏两个数据副本是有代价的。, h# F& Y8 F2 u4 X
一种替代方法是使用旧的解决方案,称为COMB,解决方案在NEWSEQUENTIALID()介绍前已使用:+ O4 X. O1 Q, p! H* ]
SELECT CAST(CAST(NEWID() AS BINARY   CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)生成uniqueidentifiers比NEWID()本身具有较好的局部性。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则