Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在SQL中从1-9然后是A-Z递增_Sql_Sql Server - Fatal编程技术网

在SQL中从1-9然后是A-Z递增

在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('

我正在创建一个11个字符长的唯一标识符。我想做的是从0000000000 1开始到0000000000 9,然后从0000000000 A开始到0000000000 Z,在我点击Z之后,我会使用下一列000000000 11到000000000 19,然后000000000 1A到000000000001Z。我将如何着手实现这一点?我知道如何分别递增字母和数字,但如何将它们放在一起

我碰巧有一个用于base 35编码的函数。对于base 36,采用它应该不会太困难:

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