Pretty old question, but if you are on SQL2017+ and wondering how to get the correct value for a sequence, even when no value at all has been taken from it, you should take into account column last_value_used
too.
When the sequence has been created for the first time, the simple statement SELECT current_value FROM sys.sequences WHERE name = 'OrderNumberSequence' ;
will return the first value that the sequence will be returning after the first next value from ..
. Then, after the first next value from
, that statement will return the same result!
Instead, it would be better to have NULL
when no value has ever been taken from the sequence, e.g. when the sequence has just been created or restarted.
Table sys.sequences
has a last_value_used
column that is NULL
when no value has been taken from the sequence or the sequence has just been restarted.
In other words, while current_value
column reports the first value that will be using the sequence on first "next value from
" and from that point on will be reporting the "current actual value", column last_value_used
will be NULL
until you ask for the first value.
From that point on, last_value_used
will be always equal to current_value
.
You can use sample snippet down here to test it by yourself.
drop sequence if exists dbo.MySequence
go
-- 1. create sequence without touching it
CREATE SEQUENCE [dbo].[MySequence]
AS [int]
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 2147483647
CYCLE
CACHE
GO
-- 2. observe current_value and last_used_value columns (should be current_value = 1, last_used_value = null)
SELECT 'Observe initial state of sequence after creation' msg, current_value, last_used_value FROM sys.sequences WHERE name = 'MySequence'
-- 3. get current value of sequence, based on last_used_value nullable state
declare @CurrentValue sql_variant
SELECT @CurrentValue = CASE WHEN last_used_value IS NULL THEN NULL ELSE current_value END
FROM sys.sequences WHERE name = 'MySequence'
select 'Current actual value' msg, @CurrentValue current_value -- should be null
-- 4. get next value from sequence
select 'Get first value from sequence' msg, next value for dbo.MySequence value -- should be 1
-- 5. observe current_value and last_used_value columns (should be current_value = 1, last_used_value = 1)
SELECT 'Observe state of sequence after getting first value' msg, current_value, last_used_value FROM sys.sequences WHERE name = 'MySequence'
-- 6. get current value of sequence, based on last_used_value nullable state
SELECT @CurrentValue = CASE WHEN last_used_value IS NULL THEN NULL ELSE current_value END
FROM sys.sequences WHERE name = 'MySequence'
select 'Current actual value' msg, @CurrentValue current_value -- should be 1
-- 7. get another value from seqeunce
select 'Get second value from sequence' msg, next value for dbo.MySequence value -- should be 2
-- 8. observe current_value and last_used_value columns (should be current_value = 2, last_used_value = 2)
SELECT 'Observe state of sequence after getting second value' msg, current_value, last_used_value FROM sys.sequences WHERE name = 'MySequence'
-- 9. get current value of sequence, based on last_used_value nullable state
SELECT @CurrentValue = CASE WHEN last_used_value IS NULL THEN NULL ELSE current_value END
FROM sys.sequences WHERE name = 'MySequence'
select 'Current actual value' msg, @CurrentValue current_value -- should be 2
current_value
in a variable I created withDECLARE
only to find outcurrent_value
is of typesql_variant
. That came as a surprise. I expected/needed anint
orbigint
and had to useCONVERT
. – Shill