Sql 生成连续的客户机号码

Sql 生成连续的客户机号码,sql,sql-server,azure-sql-database,Sql,Sql Server,Azure Sql Database,我有一个基于客户端的系统,它需要一个顺序的客户端号,格式如下 第一个客户机将获得A001,然后每个新客户机将获得A999。一旦碰到A999,它将继续到B001-B999,依此类推,直到Z001-Z999,然后通过字母表重置为AA001-AA999,依此类推 有人看到了实现这一目标的方法吗 我会使用简单的整数作为键,并使用存储过程或计算列转换为所需的格式。 我本质上不是一个数值操作,请检查计算格式的SQL 它确实假设开始时的字母不超过2个,因此客户机的数量在26*26*1000以下 select

我有一个基于客户端的系统,它需要一个顺序的客户端号,格式如下

第一个客户机将获得A001,然后每个新客户机将获得A999。一旦碰到A999,它将继续到B001-B999,依此类推,直到Z001-Z999,然后通过字母表重置为AA001-AA999,依此类推


有人看到了实现这一目标的方法吗

我会使用简单的整数作为键,并使用存储过程或计算列转换为所需的格式。 我本质上不是一个数值操作,请检查计算格式的SQL

它确实假设开始时的字母不超过2个,因此客户机的数量在26*26*1000以下

select tmp.num as client_num, CONCAT(
CASE WHEN tmp.num < 26000 THEN '' ELSE CHAR(ASCII('A') - 1 + (tmp.num / 26000)) END,
CHAR (ASCII('A') + (tmp.num / 1000) % 26),
RIGHT('000'+CAST(tmp.num % 1000 AS VARCHAR(3)),3)) as client_id
from

(select 1 as 'num'
union
select 10
union 
select 150
union 
select 1000
union
select 25999
union 
select 26000
union 
select 27000
union 
select 100000) tmp

这将为您提供从A001到ZZ999的确切数字。如果你想要更多的数字,你需要为第三个字母添加逻辑,等等。请注意,每个字母不能得到1000个数字,这会让事情变得更尴尬

WITH Numbers AS (
    SELECT 1 AS number
    UNION ALL
    SELECT number + 1 AS number FROM Numbers WHERE number < 701298)
SELECT 
    number,
    CASE WHEN number > 25974 THEN CHAR(64 + (number - 1) / 25974) ELSE '' END --This is the first letter (optional)
        + CHAR(65 + ((number - 1) / 999) % 26) --This is the second letter
        + FORMAT(CASE WHEN number < 1000 THEN number ELSE CASE WHEN number % 999 = 0 THEN 999 ELSE number % 999 END END, 'd3') --This is the three digit number
    AS client_id
FROM 
    Numbers 
OPTION (MAXRECURSION 0);
数字CTE只是为了得到合适的数字1-701298。一旦我有了它们,我需要找到第二个字母每999个数字变化一次或者第一个字母每26*999=25974个数字变化一次的边界。请注意,第一个字母将被抑制,直到需要为止

这将为您提供27*26*999客户端ID。第一个字母可以为空或A-Z=SO27选项,第二个字母可以是A-Z=26选项,数字可以是001-999=999选项。总共有701298个客户端ID


我建议使用标识列或序列来获取主键候选的内部id,然后使用函数根据该数字计算客户机id。这对多个用户更安全,等等。您可以使用一个计算列,但这是一个相当大的开销?

注释中的示例:可能不是答案,仅因为它很长就发布在这里

    CREATE SEQUENCE Numbers 
    INCREMENT BY 1 
    MINVALUE 1
    MAXVALUE 999
    CYCLE
    ;


--DROP TABLE test_DL
      Create table test_DL
    (
     VendorName varchar(50),
     VendorId as LeadingCharacters + CAST(FORMAT(TailingNumbers,'000') as VARCHAR(10)),
     LeadingCharacters VARCHAR(50),
     TailingNumbers INT DEFAULT(NEXT VALUE FOR Numbers),
     [Counter] INT IDENTITY(1,1)
     )

--ALTER SEQUENCE Numbers RESTART WITH 1

DECLARE @CONTROL INT = 0

WHILE (@CONTROL < 250)
BEGIN

INSERT INTO test_DL (VendorName)
VALUES ('THIS'),('IS'),('AN'),('EXAMPLE')

SET @CONTROL = @CONTROL + 1

END

;
WITH CTE
AS
(
SELECT *, ROW_NUMBER()OVER(ORDER BY [Counter],TailingNumbers) as RowNumber
FROM test_DL
)

UPDATE CTE
SET LeadingCharacters = CASE WHEN RowNumber <= 999 THEN 'A' WHEN 999 < RowNumber AND RowNumber < 2* 999 THEN 'B' END --The MOST ANNOYING PART is here, you need to manually category all the possibles


SELECT * FROM test_DL  --Run this to check the result

对于将来的更新,上述方法将非常愚蠢。只要给你一些想法lol

这与SQL有什么关系?你们已经有桌子了吗?如果是,请添加数据。这是一个新的数据库表,当前没有数据。存储过程。但是为什么呢?@jarlh-基本上要求有这样一个字段。@nicomp这种类型的密钥和标识没有什么不同。这很容易猜测。如果一个值被合成,它就不是一个自然键。它是一个代理密钥。我已经多次处理过这个连续的算术方案,处理起来很痛苦,因为你必须小心。需要有一个排除列表,这样你就不会有像ASS-666这样的东西。想一想所有三个字母的单词和缩写,作为一个客户号码会非常糟糕。福吉之后的那些怎么样?有太多的方法像这样为客户创造冒犯性的价值。很棒的解决方案Richard,干杯。有701298个数字,我认为它永远不会用完。或者至少在100年内可能不会:谢谢Yossi,几乎正确,但B000无效,它需要始终从001开始。
    CREATE SEQUENCE Numbers 
    INCREMENT BY 1 
    MINVALUE 1
    MAXVALUE 999
    CYCLE
    ;


--DROP TABLE test_DL
      Create table test_DL
    (
     VendorName varchar(50),
     VendorId as LeadingCharacters + CAST(FORMAT(TailingNumbers,'000') as VARCHAR(10)),
     LeadingCharacters VARCHAR(50),
     TailingNumbers INT DEFAULT(NEXT VALUE FOR Numbers),
     [Counter] INT IDENTITY(1,1)
     )

--ALTER SEQUENCE Numbers RESTART WITH 1

DECLARE @CONTROL INT = 0

WHILE (@CONTROL < 250)
BEGIN

INSERT INTO test_DL (VendorName)
VALUES ('THIS'),('IS'),('AN'),('EXAMPLE')

SET @CONTROL = @CONTROL + 1

END

;
WITH CTE
AS
(
SELECT *, ROW_NUMBER()OVER(ORDER BY [Counter],TailingNumbers) as RowNumber
FROM test_DL
)

UPDATE CTE
SET LeadingCharacters = CASE WHEN RowNumber <= 999 THEN 'A' WHEN 999 < RowNumber AND RowNumber < 2* 999 THEN 'B' END --The MOST ANNOYING PART is here, you need to manually category all the possibles


SELECT * FROM test_DL  --Run this to check the result