Sql 生成连续的客户机号码
我有一个基于客户端的系统,它需要一个顺序的客户端号,格式如下 第一个客户机将获得A001,然后每个新客户机将获得A999。一旦碰到A999,它将继续到B001-B999,依此类推,直到Z001-Z999,然后通过字母表重置为AA001-AA999,依此类推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
有人看到了实现这一目标的方法吗 我会使用简单的整数作为键,并使用存储过程或计算列转换为所需的格式。 我本质上不是一个数值操作,请检查计算格式的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