自增值

Autoincrement value

我正在处理一个本地项目,我想在我称为 serial 的 SQL 服务器 table 中设置一个列。这个值应该有下一个format/validation[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]。包含数字或大写字母的四个字符。

比如第一条记录是AAA0,然后开始从右到左递增,但是有趣的是,一旦达到AAA9,我想继续但是用字母,所以一旦达到 9,继续 A:AAAA。我的最后一个组合是 AAAZ,然后继续第二个位置,依此类推,直到我可以完成 ZZZZ.

Serial
------
AAA0
…
AAAZ
AAB0
…
AABZ
AAC0
…
AACZ
…
ZZZZ

我已经能够做类似的事情,但是例如只递增数字 0000 直到 9999 或只用字母 AAAA 到 ZZZZ(见下面的虚拟数据)。

如果您有任何意见或您以前见过这种情况,请告诉我。我将不胜感激任何帮助。

我查阅了网上的一些资料,做了这个小测试,但是还是一样,这是换字母。

CREATE TABLE #MyTable
(
    MyHeadID INT IDENTITY(0,1) NOT NULL,
    Consecutive AS 
            CHAR(MyHeadID/17576%26+65) +        --26^3
            CHAR(MyHeadID/676%26+65)  +         --26^2
            CHAR(MyHeadID/26%26+65)  +          --26^1
            CHAR(MyHeadID%26+65)                --26^0
                PERSISTED  NOT NULL,
    UniqueID VARCHAR(36) NOT NULL,
    CreatedDate datetime DEFAULT GETDATE()
)

 INSERT INTO #MyTable (UniqueID) 
    (SELECT NEWID())

 SELECT Consecutive FROM #MyTable

我们不谈 UniqueIDCreatedDate 列,它们仅用于测试目的。我创建了一个标识列,然后是字母自动增量的代码。

我在这里也发现了这个 reply 但这不是我的情况,因为在那个回复中他们将 4 个字母和 4 个数字与一个可以解析的子字符串分开。在我的例子中,我需要从右到左计算数字和字母。

这是一个可能的解决方案,以 36 进制 AAA0 计数从十进制 479879 开始。

理想情况下,您的 table 上有一个从 479879 开始的身份递增数字。使用 CTE 生成的数字 table 模拟它,下面给出了 base36 计数:

with numbers as (
    select 479879 + Row_Number() over (order by a.object_id)n 
    from sys.all_objects a cross join sys.all_objects b
)
select top 10000
    Concat(Char(((n/36/36/36) % 36) + case when (n/36/36/36) % 36 between 0 and 9 then 48 else 55 end),
    Char(((n/36/36) % 36) + case when (n/36/36) % 36 between 0 and 9 then 48 else 55 end),
    Char(((n/36) % 36) + case when (n/36) % 36 between 0 and 9 then 48 else 55 end),
    Char((n % 36) + case when n % 36 between 0 and 9 then 48 else 55 end)) Base36
from numbers 
order by n

Fiddle

之前的答案很好,但您可以这样做并用简单的数学运算涵盖所有数字。另外,我们假设您的 IDENTITY 从 1 开始。每个数字有 36 个值,因此这些值是按照指出的 base 36 编码的。正如您在 post 中提到的那样,编码先是 0 - 9,然后是 A - Z。从右到左获取某个数字 n 的各个数字,算法如下:

  1. n mod 36 是最右边的数字。
  2. n / 36 mod 36 给出倒数第二个数字。
  3. n / (36 * 36) mod 36 给出倒数第二个数字。
  4. n / (36 * 36 * 36) mod 36 给出左边的数字。

为了测试这个逻辑,我们可以写一个函数:

CREATE FUNCTION CustomNumber(@id INT)
RETURNS CHAR(4)
AS BEGIN
    RETURN CHAR((@id-1)/ POWER(36, 3)% 36+CASE WHEN (@id-1)/ POWER(36, 3)% 36 BETWEEN 0 AND 9 THEN 48 ELSE 55 END) 
    +CHAR((@id-1)/ POWER(36, 2)% 36+CASE WHEN (@id-1)/ POWER(36, 2)% 36 BETWEEN 0 AND 9 THEN 48 ELSE 55 END)
    +CHAR((@id-1)/ 36% 36+CASE WHEN (@id-1)/ 36% 36 BETWEEN 0 AND 9 THEN 48 ELSE 55 END)
    +CHAR((@id-1)% 36+CASE WHEN (@id-1)% 36 BETWEEN 0 AND 9 THEN 48 ELSE 55 END);
END;

然后我们可以通过调用它来测试这个函数以确保它能正常工作。要调用它,让我们创建一些数字。这完全是矫枉过正,但让我们将它从 1 传递到 1,000,000,这样我们就可以看到它的实际效果:

;WITH digits (I)
AS ( 
   SELECT I 
   FROM (VALUES (0), (1),(2),(3),(4),(5),(6),(7),(8),(9)) AS digits (I) ),
integers (I)
AS (SELECT D1.I + (10 * D2.I) + (100 * D3.I) + (1000 * D4.I) + (10000*D5.I) + (100000*D6.I)
    FROM digits AS D1
        CROSS JOIN digits AS D2
        CROSS JOIN digits AS D3
        CROSS JOIN digits AS D4
        CROSS JOIN digits AS D5 CROSS JOIN digits AS D6
      )
SELECT I, dbo.CustomNumber(I)
FROM integers 
WHERE I > 0
ORDER BY I;

如果你 运行 耐心等待(在我的笔记本电脑上大约需要 20 秒,但如果你不喜欢,你不必使用一百万个数字)你会看到它确实会产生您想要的结果。此时我们知道公式是正确的,因此您可以选择将其添加到 table.

一种选择是像您一样将公式用作 PERSISTED 列。另一种选择是使用触发器。您可以将公式保留为函数,也可以直接将代码放入。如果您需要超过 4 个字符,您可以按照模式轻松添加另一个字符(只需更改您加注的 POWER)。

正如我所说,前面的答案很好,我只是想展示另一种方法及其推导。我不得不多次使用不同的格式实现自定义序列,您可以使用这种通用技术。