在表值函数中使用'sys.sp_sequence_get_range'

时间:2017-12-06 09:02:26

标签: sql-server tsql sql-server-2012

场合/目标:

我有3个从1到[INT_MAX](SEQ_A,SEQ_B,SEQ_C)的整数序列,我想编写一个表值函数来从任一序列中获取一系列数字。

这是我提出的代码:

CREATE FUNCTION [dbo].[GetSequenceNumber]
(
    @TabelField VARCHAR(256),
    @Range INT
)
RETURNS @RETVALTABLE TABLE
(
    SEQUENCE_NUMBER INT
)
AS
BEGIN

    IF(ISNULL(@Range, 0) <= 0 OR @TabelField IS NULL)
        RETURN;

    DECLARE @FirstSeqNum sql_variant;
    DECLARE @LastSeqNum sql_variant;
    DECLARE @FirstSequenceNumber as INT;
    DECLARE @LastSequenceNumber as INT;

    IF @TabelField = 'FIELD_A' BEGIN
        EXEC sys.sp_sequence_get_range N'SEQ_A', @Range, @FirstSeqNum OUTPUT, @LastSeqNum OUTPUT;  
        SET @FirstSequenceNumber = CONVERT(INT, @FirstSeqNum);
        SET @LastSequenceNumber = CONVERT(INT, @LastSeqNum);

        WHILE @FirstSequenceNumber <= @LastSequenceNumber BEGIN
            INSERT INTO @RETVALTABLE SELECT @FirstSequenceNumber;
            SET @FirstSequenceNumber += 1;
        END
    END

    ELSE IF @TabelField = 'FIELD_B' BEGIN
        EXEC sys.sp_sequence_get_range N'SEQ_B', @Range, @FirstSeqNum OUTPUT, @LastSeqNum OUTPUT;  
        SET @FirstSequenceNumber = CONVERT(INT, @FirstSeqNum);
        SET @LastSequenceNumber = CONVERT(INT, @LastSeqNum);

        WHILE @FirstSequenceNumber <= @LastSequenceNumber BEGIN
            INSERT INTO @RETVALTABLE SELECT @FirstSequenceNumber;
            SET @FirstSequenceNumber += 1;
        END
    END

    ELSE IF @TabelField = 'FIELD_C' BEGIN
        EXEC sys.sp_sequence_get_range N'SEQ_C', @Range, @FirstSeqNum OUTPUT, @LastSeqNum OUTPUT;  
        SET @FirstSequenceNumber = CONVERT(INT, @FirstSeqNum);
        SET @LastSequenceNumber = CONVERT(INT, @LastSeqNum);

        WHILE @FirstSequenceNumber <= @LastSequenceNumber BEGIN
            INSERT INTO @RETVALTABLE SELECT @FirstSequenceNumber;
            SET @FirstSequenceNumber += 1;
        END
    END

    RETURN
END

为什么我这样做:

  • 我想要特定范围内的所有数字,最好是作为表格 (不像sys.sp_sequence_get_range那样只给你第一个和 最后一个数字)
  • 我不关心序列的名称,我只是“告诉”表格函数我想要哪个字段数字
  • 在将序列号插入@RETVALTABLE之前我可以做一些额外的检查(例如,擦除一些数字)。

问题:

我可以创建该函数,我可以改变它,但我无法执行它。 当我调用该函数时,我总是得到错误: “只能在函数内执行函数和某些扩展存储过程。”

嗯,错误是非常自我解释,问题可能是EXEC sys.sp_sequence_get_range N'SEQ_X', @Range, @FirstSeqNum OUTPUT, @LastSeqNum OUTPUT;部分。

问题:

如何摆脱错误?有没有比使用表值函数更好的方法来实现目标?

这里的首要任务是从特定序列(而不仅仅是起点和终点)获取某个范围内的所有数字。

(解决方案应适用于Microsoft SQL Server 2012及更高版本)

1 个答案:

答案 0 :(得分:0)

没有进入对sproc的调用(MSSQL立即开始大喊大叫并且没有停止(OUTPUT关键字,在函数内部调用proc),我想我已经找到了你这里。

此代码将返回范围中的值,而不会实际递增序列(尽管该方法是迭代的而不是基于集合的。我现在尝试设置基础):

CREATE FUNCTION dbo.GetSeqRange(@seqname VARCHAR(MAX), @start INT, @end INT)
    RETURNS @ReturnTable TABLE (
        ReturnValue INT
    )
AS
BEGIN
DECLARE @increment INT = (SELECT CONVERT(INT, increment) FROM sys.sequences WHERE [name] = @seqname)
DECLARE @i INT = @start
WHILE @i <= @end
BEGIN
    INSERT @ReturnTable VALUES(@i)
    SET @i += @increment
END
    RETURN
END

要递增序列,您可以用WHILE替换SELECT NEXT VALUE FOR <seqname>块的内部,并将其插入结果表中。如果有帮助,请告诉我!或者,如果我误解了你,那么我就会修改。