【问题标题】:Autoincrement value自动增量值
【发布时间】:2021-07-22 06:54:30
【问题描述】:

我正在处理一个本地项目,我想在我称为serial 的 SQL Server 表中设置一个列。此值应具有下一个格式/验证[A-Z0-9][A-Z0-9][A-Z0-9][A-Z0-9]。四个包含数字或大写字母的字符。

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

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

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

如果您有任何 cmet,或者您以前是否见过这种情况,请告诉我。我将不胜感激。

我查看了互联网上的一些数据并做了这个小测试,但再次,这是改变字母。

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 个数字,它可以解决。就我而言,我需要从右到左计算数字和字母。

【问题讨论】:

  • 根据问题指南,请不要发布代码、数据、错误消息等的图像 - 复制或键入问题中的文本。请保留将图像用于图表或演示渲染错误,这些无法通过文本准确描述的事情。请展示您尝试过的内容,并告诉我们您发现了什么(在本网站或其他地方)以及为什么它不能满足您的需求。
  • 只需使用一个普通的 IDENTITY 列并寻找一个执行 base 36 编码的函数以您想要的格式呈现它
  • 感谢@Dale K 的推荐。我没有尝试任何东西,因为我不知道这是否可能。我还没有在堆栈上找到任何东西。 -MG
  • @MoisesGonzaga 使用dbfiddle.uk 创建minimal reproducible example
  • 对最右边一列到达 Z 后的“编号”感到困惑,您期待AAB0 然后是AAB1 AAB2... AABZ, AAC0 etc

标签: sql-server database tsql auto-increment


【解决方案1】:

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

理想情况下,您的表上应该有一个从 479879 开始的身份递增数字。使用使用 CTE 生成的数字表进行模拟,以下给出 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

【讨论】:

  • 谢谢 Stu,根据我的描述,这基本上就是我想要完成的工作。
  • 优秀 - 听起来你可能需要调整一下,但希望能让你到达你需要的地方。
  • 是的!为了达到我的目的,我做了一些修改。谢谢。
【解决方案2】:

前面的答案很好,但您可以这样做并用简单的数学计算所有数字。另外,假设您的IDENTITY 从一开始。每个数字有 36 个值,因此这些值是如所指出的那样以 36 为基数编码。正如您在帖子中提到的,编码为 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 秒,但如果你不喜欢,你不必使用一百万个数字)你会看到它确实产生了你想要的结果想。此时我们知道公式是正确的,因此您可以选择将其添加到您的表格中。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 2011-09-17
    • 1970-01-01
    相关资源
    最近更新 更多