如何插入使用顺序 GUID 作为主键的 table?
How to INSERT into a table that uses sequential GUIDs as a primary key?
这是我正在查看的 table 的简化版本:
CREATE TABLE [dbo].[FrustratingTable]
(
[Id] Uniqueidentifier NOT NULL
, [SecondField] [datetime]
, [ThirdField] varchar(128)
)
我想在此 table 中插入新记录。我尝试了 3 种方法:
INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
SELECT newid() as Id,
'6/25/2015' as SecondField, 'Example' as ThirdField
这种方法会插入,但生成的键不像 table
中的其他键那样是一个很好的顺序 GUID
INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
SELECT NEWSEQUENTIALID() as Id, '6/25/2015' as SecondField, 'Example' as ThirdField
失败并出现错误
The newsequentialid() built-in function can only be used in a DEFAULT expression for a column of type 'uniqueidentifier' in a CREATE TABLE or ALTER TABLE statement. It cannot be combined with other operators to form a complex scalar expression.
INSERT INTO [dbo].[FrustratingTable] (SecondField,ThirdField)
SELECT '6/25/2015' as SecondField, 'Example' as ThirdField
失败并出现错误
Cannot insert the value NULL into column 'id', table 'mydatabase.dbo.frustratingtable'; column does not allow nulls. INSERT fails.
是否可以在不改变 table 定义的情况下解决这个问题?
ALTER TABLE FrustratingTable
ALTER COLUMN id uniqueidentifier not null default newsequentialid()
您可以通过使用 table 变量来做到这一点:
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 变量通过 default
设置值,我们可以使用 NEWSEQUENTIALID()
.
当然,对于非常大的数据集,暂时让两个数据副本潜伏在周围是有代价的。
另一种方法是使用称为 COMB 的旧解决方案,它在引入 NEWSEQUENTIALID()
之前使用过:
SELECT CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
生成比 NEWID()
本身具有更好局部性的 uniqueidentifiers
。
好的,如果你首先从 this answer 中获取 [IncrementGuid]
函数,
那么你可以这样做,
INSERT [dbo].[FrustratingTable]
SELECT
[dbo].[IncrementGuid](MAX([Id])),
'01/01/01',
'3'
FROM
[dbo].[FrustratingTable];
警告:
一旦您查看了其他答案中的功能,您就会同意,一定有更好的方法。
更改需要 GUID 顺序的代码。
这是我正在查看的 table 的简化版本:
CREATE TABLE [dbo].[FrustratingTable]
(
[Id] Uniqueidentifier NOT NULL
, [SecondField] [datetime]
, [ThirdField] varchar(128)
)
我想在此 table 中插入新记录。我尝试了 3 种方法:
INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
SELECT newid() as Id,
'6/25/2015' as SecondField, 'Example' as ThirdField
这种方法会插入,但生成的键不像 table
中的其他键那样是一个很好的顺序 GUIDINSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
SELECT NEWSEQUENTIALID() as Id, '6/25/2015' as SecondField, 'Example' as ThirdField
失败并出现错误
The newsequentialid() built-in function can only be used in a DEFAULT expression for a column of type 'uniqueidentifier' in a CREATE TABLE or ALTER TABLE statement. It cannot be combined with other operators to form a complex scalar expression.
INSERT INTO [dbo].[FrustratingTable] (SecondField,ThirdField)
SELECT '6/25/2015' as SecondField, 'Example' as ThirdField
失败并出现错误
Cannot insert the value NULL into column 'id', table 'mydatabase.dbo.frustratingtable'; column does not allow nulls. INSERT fails.
是否可以在不改变 table 定义的情况下解决这个问题?
ALTER TABLE FrustratingTable
ALTER COLUMN id uniqueidentifier not null default newsequentialid()
您可以通过使用 table 变量来做到这一点:
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 变量通过 default
设置值,我们可以使用 NEWSEQUENTIALID()
.
当然,对于非常大的数据集,暂时让两个数据副本潜伏在周围是有代价的。
另一种方法是使用称为 COMB 的旧解决方案,它在引入 NEWSEQUENTIALID()
之前使用过:
SELECT CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
生成比 NEWID()
本身具有更好局部性的 uniqueidentifiers
。
好的,如果你首先从 this answer 中获取 [IncrementGuid]
函数,
那么你可以这样做,
INSERT [dbo].[FrustratingTable]
SELECT
[dbo].[IncrementGuid](MAX([Id])),
'01/01/01',
'3'
FROM
[dbo].[FrustratingTable];
警告:
一旦您查看了其他答案中的功能,您就会同意,一定有更好的方法。
更改需要 GUID 顺序的代码。