newsequentialid() creating non-sequential IDs when inserts are 8s apart [duplicate] - sql-server

I'm having newsequentialid() learning problems in sql server management studio. Create a table with a uniqueidentifier column 'UniqueID', and set the default to newsequentialid().
Step 1. saving the design:
'Table_1' table
- Error validating the default for column 'UniqueID'.
Save it anyway.
Step 2. view the sql:
CREATE TABLE [dbo].[Table_1](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[UniqueID] [uniqueidentifier] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Table_1] ADD CONSTRAINT [DF_Table_1_UniqueID] DEFAULT (newsequentialid()) FOR [UniqueID]
GO
Looks reasonable.
Step 3. add some rows:
1 test 72b48f77-0e26-de11-acd4-001bfc39ff92
2 test2 92f0fc8f-0e26-de11-acd4-001bfc39ff92
3 test3 122aa19b-0e26-de11-acd4-001bfc39ff92
They don't look very sequential. ??
Edit: I have gotten it to work somewhat if the inserts are all done at once, then the unique id is sequential. On later inserts, sql server seems to forget the last sequential id, and starts a new sequence.
Running this in ssms results in squential guids:
insert into Table_1 (Name) values('test13a');
insert into Table_1 (Name) values('test14a');
insert into Table_1 (Name) values('test15a');
insert into Table_1 (Name) values('test16a');
insert into Table_1 (Name) values('test17a');

newsequentialid is primarily to solve the issue of page fragmentation when your table is clustered by a uniqueidentifier. Your table is clustered by an integer column. I set up two test tables, one where the newsequentialid column is the primary key and one where it is not (like yours), and in the primary key the GUIDs were always sequential. In the other, they were not.
I do not know the internals/technical reasons why it behaves that way, but it seems clear that newsequentialid() is only truly sequential when your table is clustered by it. Otherwise, it seems to behave similarly to newid() / RowGuid.
Also, I'm curious as to why you would want to use newsequentialid() when you don't have to. It has many downsides which newid() does not, and none of the benefits - the biggest being that newid() is not practically predictable, whereas newsequentialid() is. If you are not worried about fragmentation, what's the point?

Those values are actually "sequential" as per the definition of NEWSEQUENTIALID():
Creates a GUID that is greater than any GUID previously generated by
this function on a specified computer since Windows was started.
It doesn't say there can't be any gaps in the GUIDs, it's just that any new GUID should be greater than the previous one.
Try this:
create table #test(id int, txt varchar(50), gid uniqueidentifier)
insert into #test
select 1 ,'test','72b48f77-0e26-de11-acd4-001bfc39ff92'
union select 2, 'test2', '92f0fc8f-0e26-de11-acd4-001bfc39ff92'
union select 3, 'test3', '122aa19b-0e26-de11-acd4-001bfc39ff92'
select * from #test
order by gid asc
As you can see, the records are ordered 1, 2, 3 which is as expected.

THEY ARE SEQUENTIAL!
1 test 72b48f77-0e26-de11-acd4-001bfc39ff92
2 test2 92f0fc8f-0e26-de11-acd4-001bfc39ff92
3 test3 122aa19b-0e26-de11-acd4-001bfc39ff92
77 < 8f < 9b !!! You have to see the highest value byets, not the lowest (from right to left)

I'm not familiar with newsequentialid(), for uniqueidentifier types I call newid().

There definitely can be gaps in NewSequentialId() sequences - I've found the following causes gaps:
As soon as another call is made by another table needing a NewSequentialId()
Failed inserts
Rollbacks
(2 and 3 are similar to identity() in this respect)
For example, given 2 tables using NewSequentialId()
create table XXX(someGuid uniqueidentifier DEFAULT NEWSEQUENTIALID(), x INT)
create table YYY(someGuid uniqueidentifier DEFAULT NEWSEQUENTIALID(), y DateTime)
GO
insert into XXX(x) values(1)
insert into XXX(x) values(2)
insert into XXX(x) values(3)
GO
insert into YYY(y) values(current_timestamp)
insert into YYY(y) values(current_timestamp)
insert into YYY(y) values(current_timestamp)
GO
insert into XXX(x) values(4)
insert into XXX(x) values(5)
insert into XXX(x) values(6)
GO
SELECT * FROM XXX
6A6E85CB-CCA3-E111-9E8E-005056C00008 1
6B6E85CB-CCA3-E111-9E8E-005056C00008 2
6C6E85CB-CCA3-E111-9E8E-005056C00008 3
**CCEA7AF2-CCA3-E111-9E8E-005056C00008 4** Gap here because we 'switched' to y
CDEA7AF2-CCA3-E111-9E8E-005056C00008 5
CEEA7AF2-CCA3-E111-9E8E-005056C00008 6
SELECT * FROM YYY
8F9438E1-CCA3-E111-9E8E-005056C00008 2012-05-22 07:13:35.503
909438E1-CCA3-E111-9E8E-005056C00008 2012-05-22 07:13:41.210
919438E1-CCA3-E111-9E8E-005056C00008 2012-05-22 07:13:41.220
Also, NewSequentialId()s aren't returned to the sequence in the case of a failed insert, e.g.
insert into XXX(x) values(1)
insert into XXX(x) values(2)
BEGIN TRAN
insert into XXX(x) values(3)
insert into XXX(x) values(4)
ROLLBACK TRAN
insert into XXX(x) values(5)
insert into XXX(x) values(6)
GO
686EFE5B-CDA3-E111-9E8E-005056C00008
696EFE5B-CDA3-E111-9E8E-005056C00008
6C6EFE5B-CDA3-E111-9E8E-005056C00008
6D6EFE5B-CDA3-E111-9E8E-005056C00008
i.e. a Gap of 2 Guids rolled back
and
insert into XXX(x) values(1)
insert into XXX(x) values(2)
insert into XXX(x) values(3)
GO
insert into XXX(x) values(99999999999999) -- overflow
GO
insert into XXX(x) values(4)
insert into XXX(x) values(5)
insert into XXX(x) values(6)
go
select * from xxx
AC613611-CFA3-E111-9E8E-005056C00008 1
AD613611-CFA3-E111-9E8E-005056C00008 2
AE613611-CFA3-E111-9E8E-005056C00008 3
**B0613611-CFA3-E111-9E8E-005056C00008 4** Gap of 1 - overflow failure
B1613611-CFA3-E111-9E8E-005056C00008 5
B2613611-CFA3-E111-9E8E-005056C00008 6

NEWSEQUENTIALGUID (as every guid generated in a way that warrant their sequence) includes a part of the Guid calculated via a time stamp. So if you run the inserts at different time you'll see some gaps.
But the important part is that the Guid are "ordered" in a way that do not cause page splits (if the Guid is used in a index) and this is what happens when using the new sequential guid.

Related

Inserting to table having issue - Explicit value must be specified for identity column in table

I'm getting ready to release a stored procedure that gets info from other tables, does a pre-check, then inserts the good data into a (new) table. I'm not used to working with keys and new tables as much, and my insert into this new table I'm creating is having this error message having to do with the insert/key:
Msg 545, Level 16, State 1, Line 131
Explicit value must be specified for identity column in table 'T_1321_PNAnnotationCommitReport' either when IDENTITY_INSERT is set to ON or when a replication user is inserting into a NOT FOR REPLICATION identity column.
BEGIN
...
BEGIN
IF NOT EXISTS (SELECT * FROM sys.tables where name = N'T_1321_PNAnnotationCommitReport')
BEGIN
CREATE TABLE T_1321_PNAnnotationCommitReport (
[id] [INT] IDENTITY(1,1) PRIMARY KEY NOT NULL, --key
[progressnote_id] [INT] NOT NULL,
[form_id] [INT] NOT NULL,
[question_id] [INT],
[question_value] [VARCHAR](max),
[associatedconcept_id] [INT],
[crte_date] [DATETIME] DEFAULT CURRENT_TIMESTAMP,
[create_date] [DATETIME] --SCHED_RPT_DATE
);
print 'test';
END
END --if not exists main table
SET IDENTITY_INSERT T_1321_PNAnnotationCommitReport ON;
...
INSERT INTO dbo.T_1321_PNAnnotationCommitReport--(progressnote_id,form_id,question_id,question_value,associatedconcept_id,crte_date, create_date) **I tried with and without this commented out part and it's the same.
SELECT progressnote_id,
a.form_id,
question_id,
questionvalue,
fq.concept_id,
getdate(),
a.create_date
FROM (
SELECT form_id,
progressnote_id,
R.Q.value('#id', 'varchar(max)') AS questionid,
R.Q.value('#value', 'varchar(max)') AS questionvalue,
create_date
FROM
#tableNotes t
OUTER APPLY t.form_questions.nodes('/RESULT/QUESTIONS/QUESTION') AS R(Q)
WHERE ISNUMERIC(R.Q.value('#id', 'varchar(max)')) <> 0
) a
INNER JOIN [CKOLTP_DEV]..FORM_QUESTION fq ON
fq.form_id = a.form_id AND
fq.question_id = a.questionid
--select * from T_1321_PNAnnotationCommitReport
SET IDENTITY_INSERT T_1321_PNAnnotationCommitReport OFF;
END
Any ideas?
I looked at some comparable inserts we do at work, insert into select and error message, and insert key auto-incremented, and I think I'm doing what they do. Does anyone else see my mistake? Thanks a lot.
To repeat my comment under the question:
The error is literally telling you the problem. You turn change the IDENTITY_INSERT property to ON for the table T_1321_PNAnnotationCommitReport and then omit the column id in your INSERT. If you have enabled IDENTITY_INSERT you need to supply a value to that IDENTITY, just like the error says.
We can easily replicate this problem with the following batches:
CREATE TABLE dbo.MyTable (ID int IDENTITY(1,1),
SomeValue varchar(20));
GO
SET IDENTITY_INSERT dbo.MyTable ON;
--fails
INSERT INTO dbo.MyTable (SomeValue)
VALUES('abc');
GO
If you want the IDENTITY value to be autogenerated, then leave IDENTITY_INSERT set to OFF and omit the column from the INSERT (like above):
SET IDENTITY_INSERT dbo.MyTable OFF; --Shouldn't be needed normally, but we manually changed it before
--works, as IDENTITY_INSERT IS OFF
INSERT INTO dbo.MyTable (SomeValue)
VALUES('abc');
If you do specifically want to define the value for the IDENTITY, then you need to both set IDENTITY_INSERT to ON and provide a value in the INSERT statement:
SET IDENTITY_INSERT dbo.MyTable ON;
--works
INSERT INTO dbo.MyTable (ID,SomeValue)
VALUES(10,'def');
GO
SELECT *
FROM dbo.MyTable;
IDENTITY_INSERT doesn't mean "Get the RDBMS to 'insert' the value" it means that you want to want to tell the RDBMS what value to INSERT. This is covered in the opening sentence of the documentation SET IDENTITY_INSERT (Transact-SQL):
Allows explicit values to be inserted into the identity column of a table.
(Emphasis mine)

is it possible that an auto increment field duplicates?

I have a table which has several field including:
contact_id
phone
phone_id
contact_id and phone are primary keys and phone_id is an auto increment field. I want to use it to recognize a certain entry. So I want to know that is it possible to duplicate that non primary field when I'm entering data.
Unless there is no constraint, some unique index, you can duplicate values in that column, because 1) you can turn identity_insert on, 2) you can reseed increments.
Here is a proof:
CREATE TABLE #test(id INT IDENTITY(1, 1))
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
SET IDENTITY_INSERT #test ON
INSERT INTO #test(id) VALUES(1)
SET IDENTITY_INSERT #test OFF
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
DBCC CHECKIDENT ('#test', RESEED, 1);
INSERT INTO #test DEFAULT VALUES
INSERT INTO #test DEFAULT VALUES
SELECT * FROM #test
DROP TABLE #test
Output:
id
1
2
3
1
4
5
2
3
The short answer is Yes, it's possible.
SQL Server does not force a unique constraint on identity columns, meaning that the can have duplicated values, however, Sql server will not generate duplicate values itself in an identity column.
Identity columns in sql server are populated by the sql server itself when you insert a row to the table.
However, you can specify a value to them by using SET IDENTITY_INSERT before the insert statement.
There are a couple of things that you should be aware of:
Setting identity_insert on is per table. you can only set it for one table at the time.
Until you set the identity_insert back off, any insert statement to that table will have to specify a value for the identity column.
you can't use set identity insert on for more then one table on a single session. therefor after you've done inserting records to the table you must set the identity_insert back off on that table.

Set A Field the same as ID (IDENTITY) in the insert

I have a Code (int) in my table, the ID is set to identity. How can I set a default value for my code to be filled by the same value az ID? I mean Identity.
You could use an after insert trigger:
create table TestTable (id int identity, col1 int)
go
create trigger TestTrigger on TestTable after insert
as begin
update TestTable
set col1 = id
where col1 is null
and id in (select id from inserted)
end
go
Test code:
insert TestTable default values
insert TestTable (col1) values (666)
insert TestTable default values
select * from TestTable
In general, I try to stay clear of triggers. In the long run using a stored procedure for insert is much more maintainable:
create procedure dbo.InsertTestRow(
#col1 int)
as
insert TestTable (col1) values (#col1)
if #col1 is null
begin
update TestTable
set col1 = id
where id = SCOPE_IDENTITY()
end
If it always has the same value - why don't you just drop that field. Otherwise it can be maintained with triggers (BEFORE INSERT one).
I'm looking for something in the
default value! If it is null it should
be filled with the same value as id
but if it is provided with some value,
it should keep that value
You could solve the issue by using coalesce in your queries instead.
create table T (ID int identity, ID2 int)
insert into T values (default)
insert into T values (null)
insert into T values (78)
select
ID,
coalesce(ID2, ID) as ID2
from T
Result
ID ID2
-- ---
1 1
2 2
3 78
Assuming your table's ID is an Identity column, you could consider using a constraint:
ALTER TABLE MyTable
ADD CONSTRAINT MyTableCodeDefault
DEFAULT IDENT_CURRENT('MyTable') FOR Code
This works for these use cases:
INSERT INTO MyTable DEFAULT VALUES
INSERT INTO MyTable ({columns NOT including 'Code'})
VALUES ({value list matching insert columns})
INSERT INTO MyTable (Code) VALUES (666)
INSERT INTO MyTable (Code) SELECT 8 UNION SELECT 13 UNION SELECT 21
But it does not work for bulk inserts:
INSERT INTO MyTable ({columns NOT including 'Code'})
SELECT {value list matching insert columns}
UNION
SELECT {value list matching insert columns}
UNION
SELECT {value list matching insert columns}
This restriction may seem onerous, but in my practical experience, it's rarely a problem. Most of the use cases I've encountered that need a default value involve user/UI 'convenience': don't force the user to pick a value if they don't want to.
OTOH, rarely do I encounter bulk insert situations where it's impractical to specify the value for the columns you're targeting.
You could use computed column, like this:
if object_id('TempTable') is not null drop table TempTable
create table TempTable (Id int identity(1,1), Code as Id)
insert into TempTable
default values
insert into TempTable
default values
insert into TempTable
default values
select * from TempTable
Of course if you have other columns, then you dont need default values:
if object_id('TempTable') is not null drop table TempTable
create table TempTable (Id int identity(1,1), Code as Id, SomethingElse int)
insert into TempTable (SomethingElse)
select 10 union all
select 11 union all
select 12
select * from TempTable
But, like zerkms said - why do you need two columns that are same?
If the field is an Identity field in SQL Server, the database engine will take care of its value. What we normally do is to read the record back (after inserting) to get to the generated Id.
EDIT: It sounds like you are trying to "override" the identity? If so, before you insert, run:
SET IDENTITY_INSERT [tableName] ON
You'll have to be careful not to insert a value that already exists. This can get tricky, though. So maybe consider removing the identity property altogether, and managing the default values yourself?

How Do You Tell What Next Identity Column Will Be?

Is there a tsql query to tell what SQL server identity column value it expects to use for the next row insert?
Edited to add:
I deleted and recreated a table with
[personID] [int] IDENTITY(1,1) NOT NULL
as part of my CREATE TABLE command. I've also attempted to reseed identity columns while removing all information in that table and that hasn't always worked. It got me to wondering if there was a way to see what SQL expected to use for your next identity column number.
You probably want to use SCOPE_IDENTITY not ##IDENTITY to restrict it to the identity value in the current scope. This avoids getting new identity values inserted by triggers into other tables and not the table you just inserted into.
But you can calculate what the next identity value is
SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable
The problem is you aren't guaranteed that is the value.
You'd have to have a lock such that other inserts are denied on the table when running it to ensure the value is accurate. Also after you run out of 32 bit integers I don't know what the logic is. I don't know whether it rolls over or fails.
Edit:
I just tested this (see below for SQL) and it doesn't return the correct value when there is no data.
And reseeding with DBCC CHECKIDENT ('tablename', RESEED, 200) actually resulted in the next value being 201 not 200.
CREATE TABLE willtest (myid integer IDENTITY(1,1), myvalue varchar(255))
SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')
INSERT INTO willtest (myvalue)
VALUES ('1')
INSERT INTO willtest (myvalue)
VALUES ('2')
INSERT INTO willtest (myvalue)
VALUES ('3')
INSERT INTO willtest (myvalue)
VALUES ('4')
INSERT INTO willtest (myvalue)
VALUES ('5')
INSERT INTO willtest (myvalue)
VALUES ('6')
INSERT INTO willtest (myvalue)
VALUES ('7')
INSERT INTO willtest (myvalue)
VALUES ('8')
SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')
DBCC CHECKIDENT ('willtest', RESEED, 200)
SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')
INSERT INTO willtest (myvalue)
VALUES ('200')
INSERT INTO willtest (myvalue)
VALUES ('201')
INSERT INTO willtest (myvalue)
VALUES ('202')
INSERT INTO willtest (myvalue)
VALUES ('203')
INSERT INTO willtest (myvalue)
VALUES ('204')
INSERT INTO willtest (myvalue)
VALUES ('205')
INSERT INTO willtest (myvalue)
VALUES ('206')
INSERT INTO willtest (myvalue)
VALUES ('207')
SELECT IDENT_CURRENT('willtest') + IDENT_INCR('willtest')
SELECT * FROM willtest
DROP TABLE willtest
No, there isn't any guaranteed way (although you can certainly find out what the next value might be, another command might go and use it before you can make any use of it). The only guaranteed value you can retrieve is the previously inserted identity value through SCOPE_IDENTITY() (which will return the identity value last generated for the current scope).
It's questionable what purpose why one would need to know the value before (when using an automatically incremented seeded identity column).
If you need to know the value before, then I recommend generating the ids yourself. You can do this with an ids table keyed on the table name, or, if you have scalability concerns (and you are using transactions) you can have an id table for each table that needs an id which would have the id to be inserted (and subsequently incremented).
Or, you could use a GUID, and you would be able to easily generate these on the client side before sending it to your database.
This piece of sql will give you the next identity column value (there are probably many reasons not to repeat this snippet in production code)
declare #nextid int;
declare #previousid int;
begin tran
insert into dbo.TestTable (Col1) values ('11');
select #nextid = SCOPE_IDENTITY();
rollback tran
select #previousid = #nextid -1
DBCC CHECKIDENT('dbo.TestTable', RESEED, #previousid);
select #nextid
this stackoverflow question gives some extra information - sql-identity-autonumber-is-incremented-even-with-a-transaction-rollback
SELECT IDENT_CURRENT('mytable') + IDENT_INCR('mytable') FROM mytable
Since you seed from 1 and increment by 1 (IDENTITY(1,1)), I'm wondering if you can create a procedure where you can set a variable like "Select ##IDENTITY + 1" or something like that.
Use GUID columns for your primary keys. Unless you have billions of records and thousands of requests per second, you probably won't notice the performance difference. But unless you like spending far too much time dealing with stupid issues like this, you will notice the difference in your stress level and life expectancy.

sql server 2008 newsequentialid() problem

I'm having newsequentialid() learning problems in sql server management studio. Create a table with a uniqueidentifier column 'UniqueID', and set the default to newsequentialid().
Step 1. saving the design:
'Table_1' table
- Error validating the default for column 'UniqueID'.
Save it anyway.
Step 2. view the sql:
CREATE TABLE [dbo].[Table_1](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[UniqueID] [uniqueidentifier] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Table_1] ADD CONSTRAINT [DF_Table_1_UniqueID] DEFAULT (newsequentialid()) FOR [UniqueID]
GO
Looks reasonable.
Step 3. add some rows:
1 test 72b48f77-0e26-de11-acd4-001bfc39ff92
2 test2 92f0fc8f-0e26-de11-acd4-001bfc39ff92
3 test3 122aa19b-0e26-de11-acd4-001bfc39ff92
They don't look very sequential. ??
Edit: I have gotten it to work somewhat if the inserts are all done at once, then the unique id is sequential. On later inserts, sql server seems to forget the last sequential id, and starts a new sequence.
Running this in ssms results in squential guids:
insert into Table_1 (Name) values('test13a');
insert into Table_1 (Name) values('test14a');
insert into Table_1 (Name) values('test15a');
insert into Table_1 (Name) values('test16a');
insert into Table_1 (Name) values('test17a');
newsequentialid is primarily to solve the issue of page fragmentation when your table is clustered by a uniqueidentifier. Your table is clustered by an integer column. I set up two test tables, one where the newsequentialid column is the primary key and one where it is not (like yours), and in the primary key the GUIDs were always sequential. In the other, they were not.
I do not know the internals/technical reasons why it behaves that way, but it seems clear that newsequentialid() is only truly sequential when your table is clustered by it. Otherwise, it seems to behave similarly to newid() / RowGuid.
Also, I'm curious as to why you would want to use newsequentialid() when you don't have to. It has many downsides which newid() does not, and none of the benefits - the biggest being that newid() is not practically predictable, whereas newsequentialid() is. If you are not worried about fragmentation, what's the point?
Those values are actually "sequential" as per the definition of NEWSEQUENTIALID():
Creates a GUID that is greater than any GUID previously generated by
this function on a specified computer since Windows was started.
It doesn't say there can't be any gaps in the GUIDs, it's just that any new GUID should be greater than the previous one.
Try this:
create table #test(id int, txt varchar(50), gid uniqueidentifier)
insert into #test
select 1 ,'test','72b48f77-0e26-de11-acd4-001bfc39ff92'
union select 2, 'test2', '92f0fc8f-0e26-de11-acd4-001bfc39ff92'
union select 3, 'test3', '122aa19b-0e26-de11-acd4-001bfc39ff92'
select * from #test
order by gid asc
As you can see, the records are ordered 1, 2, 3 which is as expected.
THEY ARE SEQUENTIAL!
1 test 72b48f77-0e26-de11-acd4-001bfc39ff92
2 test2 92f0fc8f-0e26-de11-acd4-001bfc39ff92
3 test3 122aa19b-0e26-de11-acd4-001bfc39ff92
77 < 8f < 9b !!! You have to see the highest value byets, not the lowest (from right to left)
I'm not familiar with newsequentialid(), for uniqueidentifier types I call newid().
There definitely can be gaps in NewSequentialId() sequences - I've found the following causes gaps:
As soon as another call is made by another table needing a NewSequentialId()
Failed inserts
Rollbacks
(2 and 3 are similar to identity() in this respect)
For example, given 2 tables using NewSequentialId()
create table XXX(someGuid uniqueidentifier DEFAULT NEWSEQUENTIALID(), x INT)
create table YYY(someGuid uniqueidentifier DEFAULT NEWSEQUENTIALID(), y DateTime)
GO
insert into XXX(x) values(1)
insert into XXX(x) values(2)
insert into XXX(x) values(3)
GO
insert into YYY(y) values(current_timestamp)
insert into YYY(y) values(current_timestamp)
insert into YYY(y) values(current_timestamp)
GO
insert into XXX(x) values(4)
insert into XXX(x) values(5)
insert into XXX(x) values(6)
GO
SELECT * FROM XXX
6A6E85CB-CCA3-E111-9E8E-005056C00008 1
6B6E85CB-CCA3-E111-9E8E-005056C00008 2
6C6E85CB-CCA3-E111-9E8E-005056C00008 3
**CCEA7AF2-CCA3-E111-9E8E-005056C00008 4** Gap here because we 'switched' to y
CDEA7AF2-CCA3-E111-9E8E-005056C00008 5
CEEA7AF2-CCA3-E111-9E8E-005056C00008 6
SELECT * FROM YYY
8F9438E1-CCA3-E111-9E8E-005056C00008 2012-05-22 07:13:35.503
909438E1-CCA3-E111-9E8E-005056C00008 2012-05-22 07:13:41.210
919438E1-CCA3-E111-9E8E-005056C00008 2012-05-22 07:13:41.220
Also, NewSequentialId()s aren't returned to the sequence in the case of a failed insert, e.g.
insert into XXX(x) values(1)
insert into XXX(x) values(2)
BEGIN TRAN
insert into XXX(x) values(3)
insert into XXX(x) values(4)
ROLLBACK TRAN
insert into XXX(x) values(5)
insert into XXX(x) values(6)
GO
686EFE5B-CDA3-E111-9E8E-005056C00008
696EFE5B-CDA3-E111-9E8E-005056C00008
6C6EFE5B-CDA3-E111-9E8E-005056C00008
6D6EFE5B-CDA3-E111-9E8E-005056C00008
i.e. a Gap of 2 Guids rolled back
and
insert into XXX(x) values(1)
insert into XXX(x) values(2)
insert into XXX(x) values(3)
GO
insert into XXX(x) values(99999999999999) -- overflow
GO
insert into XXX(x) values(4)
insert into XXX(x) values(5)
insert into XXX(x) values(6)
go
select * from xxx
AC613611-CFA3-E111-9E8E-005056C00008 1
AD613611-CFA3-E111-9E8E-005056C00008 2
AE613611-CFA3-E111-9E8E-005056C00008 3
**B0613611-CFA3-E111-9E8E-005056C00008 4** Gap of 1 - overflow failure
B1613611-CFA3-E111-9E8E-005056C00008 5
B2613611-CFA3-E111-9E8E-005056C00008 6
NEWSEQUENTIALGUID (as every guid generated in a way that warrant their sequence) includes a part of the Guid calculated via a time stamp. So if you run the inserts at different time you'll see some gaps.
But the important part is that the Guid are "ordered" in a way that do not cause page splits (if the Guid is used in a index) and this is what happens when using the new sequential guid.

Resources