问题
Here is a simplified version of the table I am looking at:
CREATE TABLE [dbo].[FrustratingTable]
(
[Id] Uniqueidentifier NOT NULL
, [SecondField] [datetime]
, [ThirdField] varchar(128)
)
I want to insert new records into this table. I have tried 3 approaches:
INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
SELECT newid() as Id,
'6/25/2015' as SecondField, 'Example' as ThirdField
This approach inserts, but the resulting key isn't a nice sequential GUID like the other ones in the table
INSERT INTO [dbo].[FrustratingTable] (Id, SecondField, ThirdField)
SELECT NEWSEQUENTIALID() as Id, '6/25/2015' as SecondField, 'Example' as ThirdField
This fails with error
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
This fails with the error
Cannot insert the value NULL into column 'id', table 'mydatabase.dbo.frustratingtable'; column does not allow nulls. INSERT fails.
Is it possible to solve this without altering the table definition?
回答1:
You may be able to do this by way of using a table variable:
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
Results:
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
Since the table variable sets the value via a default
, we're allowed to use NEWSEQUENTIALID()
.
Of course, for very large data sets, there's a penalty in temporarily having two copies of the data lurking around.
An alternative would be to use an older solution, called COMBs, which were used before NEWSEQUENTIALID()
was introduced:
SELECT CAST(CAST(NEWID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)
Generates uniqueidentifiers
with better locality than NEWID()
by itself does.
回答2:
Ok, if first yout take the [IncrementGuid]
function from this answer,
then you can do something like this,
Fiddle Here
INSERT [dbo].[FrustratingTable]
SELECT
[dbo].[IncrementGuid](MAX([Id])),
'01/01/01',
'3'
FROM
[dbo].[FrustratingTable];
Caveat:
Once you reviewed the function in the other answer, you'll agree, there must be a better way.
Change the code that needs the GUIDs to be sequential.
回答3:
ALTER TABLE FrustratingTable
ALTER COLUMN id uniqueidentifier not null default newsequentialid()
来源:https://stackoverflow.com/questions/31073409/how-to-insert-into-a-table-that-uses-sequential-guids-as-a-primary-key