我正在使用 SQL Server 2012 (v11.0.2100),我想创建一个以随机(动态)数字开头的序列,但我无法做到这一点,我也努力为此找到一个好的解决方案但我还没有找到令我满意的东西。
我尝试过但失败的案例:
DECLARE @sth bigint
SET @sth = 1000
ALTER SEQUENCE StreamEntrySequence
RESTART WITH @sth;
错误:
“@sth”附近的语法不正确
一个丑陋的解决方案
declare @sth bigint;
declare @i bigint;
SET @sth = 100000 ;
while @i<@sth;
BEGIN
SET @i= next value for StreamEntrySequence;
END
还有其他方法可以将当前值或起始值设置为随机值吗?也许使用服务器程序?
正如已经提到的,这将需要动态 SQL,因为 alterequence 需要
restart
参数的常量。
你可能会做这样的事情,然后:
DECLARE @sth bigint;
SET @sth = 1000;
DECLARE @sql nvarchar(max);
SET @sql = N'ALTER SEQUENCE StreamEntrySequence RESTART WITH ' + cast(@sth as nvarchar(20)) + ';';
EXEC SP_EXECUTESQL @sql;
尝试
ALTER SEQUENCE foo.fee
RESTART
或者:
ALTER SEQUENCE foo.fee
RESTART WITH 1
这是一种替代解决方案(它保留原始参数,并且仍然不需要循环来一次递增序列一个)。基本上,分三步进行;将 INCREMENT 值更改为所需 CURRENT_VALUE 与实际 CURRENT_VALUE 之间的差值,调用序列将其增加差值,然后恢复原始 INCRMENT 值。
DECLARE @SchemaName VARCHAR(255) = 'SCHEMA'
DECLARE @SequenceName VARCHAR(255) = 'SEQUENCE'
DECLARE @CurrentValueRequired INT
SELECT @CurrentValueRequired = 1000000 --could be assigned from a SELECT query as well
PRINT '@CurrentValueRequired=' + CAST(@CurrentValueRequired AS VARCHAR(20))
DECLARE @CurrentValueActual BIGINT
DECLARE @LastUsedValue BIGINT
DECLARE @IncrementValue BIGINT
DECLARE @CurrentValueDifference BIGINT
SELECT @CurrentValueActual = CAST(CURRENT_VALUE AS BIGINT),
@LastUsedValue = CAST(LAST_USED_VALUE AS BIGINT),
@IncrementValue = CAST(INCREMENT AS BIGINT)
FROM SYS.SEQUENCES
WHERE NAME = @SequenceName
SET @CurrentValueDifference = @CurrentValueRequired - @CurrentValueActual
PRINT '@CurrentValueActual=' + CAST(@CurrentValueActual AS VARCHAR(30))
PRINT '@LastUsedValue=' + CASE WHEN @LastUsedValue IS NULL THEN 'NULL' ELSE CAST(@LastUsedValue AS VARCHAR(30)) END
PRINT '@IncrementValue=' + CAST(@IncrementValue AS VARCHAR(30))
PRINT '@CurrentValueDifference=' + cast(@CurrentValueDifference AS VARCHAR(30))
IF @CurrentValueDifference > 0
BEGIN
DECLARE @sql NVARCHAR(MAX)
-- If LAST_USED_VALUE is NULL, then the sequence has NEVER been accessed since it's creation. Call it once so that it's START_WITH value becomes the LAST_USED_VALUE.
IF @LastUsedValue IS NULL
BEGIN
PRINT '@LastUsedValue IS NULL'
SET @sql = N'DECLARE @NextValue BIGINT; SELECT @NextValue = NEXT VALUE FOR ' + @SchemaName + '.' + @SequenceName
PRINT @sql
EXEC SP_EXECUTESQL @sql;
SELECT @CurrentValueActual = CAST(CURRENT_VALUE AS BIGINT), @LastUsedValue = CAST(LAST_USED_VALUE AS BIGINT) FROM SYS.SEQUENCES WHERE NAME = @SequenceName
PRINT '@CurrentValueActual=' + CAST(@CurrentValueActual AS VARCHAR(30))
PRINT '@LastUsedValue=' + CASE WHEN @LastUsedValue IS NULL THEN 'NULL' ELSE CAST(@LastUsedValue AS VARCHAR(30)) END
END
-- Set the INCREMENT value to the difference between the required CURRENT_VALUE and the actual CURRENT_VALUE
SET @sql = N'ALTER SEQUENCE ' + @SchemaName + '.' + @SequenceName + ' INCREMENT BY ' + CAST(@CurrentValueDifference AS NVARCHAR(30)) + ';'
PRINT @sql
EXEC SP_EXECUTESQL @sql;
-- Now call the sequence to increment it once by the difference value
SET @sql = N'DECLARE @NextValue BIGINT; SELECT @NextValue = NEXT VALUE FOR ' + @SchemaName + '.' + @SequenceName
PRINT @sql
EXEC SP_EXECUTESQL @sql;
SELECT @CurrentValueActual = CAST(CURRENT_VALUE AS BIGINT), @LastUsedValue = CAST(LAST_USED_VALUE AS BIGINT) FROM SYS.SEQUENCES WHERE NAME = @SequenceName
PRINT '@CurrentValueActual=' + CAST(@CurrentValueActual AS VARCHAR(30))
PRINT '@LastUsedValue=' + CASE WHEN @LastUsedValue IS NULL THEN 'NULL' ELSE CAST(@LastUsedValue AS VARCHAR(30)) END
-- Set the INCREMENT back to the original value
SET @sql = N'ALTER SEQUENCE ' + @SchemaName + '.' + @SequenceName + ' INCREMENT BY ' + CAST(@IncrementValue AS NVARCHAR(30)) + ';'
PRINT @sql
EXEC SP_EXECUTESQL @sql;
END
ELSE
BEGIN
PRINT 'NOTHING TO DO!'
END