使用sql存储过程生成字母数字序列

时间:2016-05-13 07:08:19

标签: sql sql-server

我需要使用主键自动生成员工参考号唯一序列。示例Refno:(A0001-Z9999)现在已经执行了最大计数(Z9999) 我要生成的下一个序列:

AA001-AA999,
AB001-AB999, 
AZ999-BA001
BC001-BZ999,
CA001-CZ999,
ZA001-ZZ999..LIKE THIS..IN sql server stored procedure..

...ZZ999 LIKE THIS

2 个答案:

答案 0 :(得分:1)

你可以这样做。

首先创建一个SEQUENCE来生成从1开始的整数序列号。

CREATE SEQUENCE dbo.MySeq AS INT
    START WITH 1
    INCREMENT BY 1;

然后创建一个存储过程,生成所需格式的序列代码。

CREATE PROCEDURE dbo.up_GetNextSequence
(
    @seq nchar(5) out
)
AS
DECLARE @i int = NEXT VALUE FOR dbo.MySeq;

IF @i > 685323
BEGIN
    RAISERROR(N'Sequence is out of range.', 16, 0);
END

IF @i < 10000
BEGIN
    SET @seq = N'A' + FORMAT(@i, 'D4');
END
ELSE
BEGIN
    DECLARE @j int;
    SET @j = @i - 9999;

    DECLARE @k int;
    SET @k = ((@j - 1) % 999) + 1;

    DECLARE @l int;
    SET @l = (@j - 1) / 999;

    DECLARE @m int;
    SET @m = (@l % 26) + 65;

    DECLARE @n int;
    SET @n = (@l / 26) + 65;

    SET @seq = NCHAR(@n) + NCHAR(@m) + FORMAT(@k, 'D3');
END;

然后测试存储过程。

DECLARE @seq nchar(5);
EXEC up_GetNextSequence @seq output;
SELECT @seq AS '@seq'

enter image description here

再打四次,我们到达“A0005”。

enter image description here

要测试第一个断点,请更改序列对象,使其返回9999.然后再次执行测试代码。

ALTER SEQUENCE dbo.MySeq
   RESTART WITH 9999;

enter image description here

enter image description here

enter image description here

等等......

ALTER SEQUENCE dbo.MySeq
    RESTART WITH 10998;

enter image description here

enter image description here

enter image description here

ALTER SEQUENCE dbo.MySeq
    RESTART WITH 35973;

enter image description here

enter image description here

ALTER SEQUENCE dbo.MySeq
    RESTART WITH 659349;

enter image description here

enter image description here

测试当它到达允许范围的末尾时会发生什么。

ALTER SEQUENCE dbo.MySeq
    RESTART WITH 685323;

enter image description here

再次执行存储过程并引发错误,表示序列超出范围。这是设计的。

enter image description here

答案 1 :(得分:1)

此查询将为您提供所需的所有值:

--here we take all the english alphabet
;WITH chars AS (
SELECT CHAR(65) as chars, 65 as [level]
UNION ALL
SELECT CHAR([level]+1), [level]+1
FROM chars
WHERE [level]-65 < 25
), cte AS ( -- Here we take didits from 1 to 999
SELECT 1 as digits
UNION ALL
SELECT digits+1
FROM cte
WHERE digits < 999
), codes AS ( -- here we get all chars combinations "AA", "AB" etc
SELECT c1.chars+c2.chars as code
FROM chars c1
cross join chars c2
)

--And here come cortesian join to get all refnomes ou need
SELECT code + CASE WHEN LEN(digits) = 1 THEN CONCAT('00',cast(digits as nvarchar(1)))
            WHEN LEN(digits) = 2 THEN CONCAT('0',cast(digits as nvarchar(2)))
            ELSE cast(digits as nvarchar(3)) END  as Refno
FROM cte
CROSS JOIN codes
ORDER BY code
OPTION (maxrecursion 1000)

输出:

Refno
AA001
AA002
AA003
AA004
AA005
AA006
AA007
AA008
AA009
AA010
AA011
AA012
AA013
AA014
AA015
AA016
AA017
...
etc
ZZ999

~675324行

您可以将结果放入某个表和存储过程中,从该表中返回所需的值。