在SQL中从1-9然后是A-Z递增
我正在创建一个11个字符长的唯一标识符。我想做的是从0000000000 1开始到0000000000 9,然后从0000000000 A开始到0000000000 Z,在我点击Z之后,我会使用下一列000000000 11到000000000 19,然后000000000 1A到000000000001Z。我将如何着手实现这一点?我知道如何分别递增字母和数字,但如何将它们放在一起 我碰巧有一个用于base 35编码的函数。对于base 36,采用它应该不会太困难:在SQL中从1-9然后是A-Z递增,sql,sql-server,Sql,Sql Server,我正在创建一个11个字符长的唯一标识符。我想做的是从0000000000 1开始到0000000000 9,然后从0000000000 A开始到0000000000 Z,在我点击Z之后,我会使用下一列000000000 11到000000000 19,然后000000000 1A到000000000001Z。我将如何着手实现这一点?我知道如何分别递增字母和数字,但如何将它们放在一起 我碰巧有一个用于base 35编码的函数。对于base 36,采用它应该不会太困难: IF OBJECT_ID('
IF OBJECT_ID('DCA.dxConvert_From_Decimal_To_35Base') IS NOT NULL
BEGIN
DROP FUNCTION [DCA].[dxConvert_From_Decimal_To_35Base]
END
GO
CREATE FUNCTION DCA.dxConvert_From_Decimal_To_35Base(@DECIMAL_NUMBER INT)
RETURNS VARCHAR(20)
AS
BEGIN
DECLARE @MOD INT
DECLARE @TEMP_VALUE VARCHAR(20)
DECLARE @BASE_DIGITS VARCHAR(100)
DECLARE @BASE INT
SET @BASE = 35
SET @TEMP_VALUE = ''
SET @BASE_DIGITS = '0123456789ABCDEFGHIJKLMNPQRSTUVWXYZ'
IF @DECIMAL_NUMBER = 0
BEGIN --0 STAYS 0
RETURN 0
END
WHILE @DECIMAL_NUMBER <> 0
BEGIN
SET @MOD = @DECIMAL_NUMBER % @BASE
SET @TEMP_VALUE = SUBSTRING(@BASE_DIGITS, @MOD + 1 , 1) + @TEMP_VALUE
SET @DECIMAL_NUMBER = @DECIMAL_NUMBER / @BASE
END
RETURN @TEMP_VALUE
END
结果:
+--------+------------------+
| number | (No column name) |
+--------+------------------+
| 0 | 0 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 10 | A |
| 11 | B |
| 12 | C |
| 13 | D |
| 14 | E |
| 15 | F |
| 16 | G |
| 17 | H |
| 18 | I |
| 19 | J |
| 20 | K |
| 21 | L |
| 22 | M |
| 23 | N |
| 24 | P |
| 25 | Q |
| 26 | R |
| 27 | S |
| 28 | T |
| 29 | U |
| 30 | V |
| 31 | W |
| 32 | X |
| 33 | Y |
| 34 | Z |
| 35 | 10 |
| 36 | 11 |
| 37 | 12 |
+--------+------------------+
您可以将整数转换为十六进制,然后添加“000…”
DECLARE @t TABLE (value VARCHAR(11));
DECLARE @seq int;
SET @seq = 0;
WHILE @seq < 100
BEGIN
INSERT INTO @t VALUES
(
RIGHT(REPLICATE('0', 11) + sys.fn_varbintohexsubstring(0, @seq, 1, 0), 11)
);
SET @seq += 1;
END
SELECT * FROM @t;
dbfiddle正如Alex K.所说,在表中使用主键的标识1,1,并使用如下方式计算疯狂基36值的值:
declare @Val BIGINT
set @val = 45643
DECLARE @Result VARCHAR(9) = ''
WHILE (@Val > 0)
BEGIN
SELECT @Result = CHAR(@Val % 36 + CASE WHEN @Val % 36 < 10 THEN 48 ELSE 55 END) + @Result,
@Val = FLOOR(@Val/36)
END
select right('00000000000' + @Result, 11)
with a as (
select i
from (values('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('A'),('B'),('C')) v(i)
)
select a1.i + a2.i + a3.i + a4.i Value,
row_number() over(order by a1.i + a2.i + a3.i + a4.i) rn
from a a1, a a2, a a3, a a4
如果您愿意使用十六进制,那么可以使用计算列
USE [Test]
GO
/****** Object: Table [dbo].[hexRep] Script Date: 4/11/2018 9:52:44 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[hexRep](
[iden] [int] IDENTITY(1,1) NOT NULL,
[hex] AS (CONVERT([char](8),CONVERT([varbinary](8),[iden]),(2))),
[val] [varchar](50) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
你到底为什么要这么做?这里面有很多大问题。您有并发性问题。你必须担心各种你不想要的词。为什么不直接使用一个标识或唯一标识符并使用它呢?存储一个int,然后如果你真的需要转换为基数36以获得1..Z,10..1Z的序数,你只需要基数36编码一个整数。你的问题基本上和我的一样,尽管那一个也没有答案。但是,搜索base 36 sql server给了我很多潜在的线索。您存储值并获取下一个值的方法就是我刚才提到的并发性问题。当两个或多个用户同时尝试获取下一个值时会发生什么情况?您有向多个请求提供相同下一个值的风险。你可以克服这一点,但你必须小心使用一些锁定提示。你不想从0000Z到00010而不是00011吗?
with a as (
select i
from (values('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('A'),('B'),('C')) v(i)
)
select a1.i + a2.i + a3.i + a4.i Value,
row_number() over(order by a1.i + a2.i + a3.i + a4.i) rn
from a a1, a a2, a a3, a a4
USE [Test]
GO
/****** Object: Table [dbo].[hexRep] Script Date: 4/11/2018 9:52:44 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[hexRep](
[iden] [int] IDENTITY(1,1) NOT NULL,
[hex] AS (CONVERT([char](8),CONVERT([varbinary](8),[iden]),(2))),
[val] [varchar](50) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO