3

在我们的数据库中,我们对数字 0 到 9 和字母表中所有非誓言的字母组合的所有内容都使用主键。包括字母 Y。我创建了这张表来组织它。

CREATE Table Base31
(ID varchar(1),
 NumberValue bigint)

GO

Insert into Base31 SELECT '0', '0'
Insert into Base31 SELECT '1', '1'
Insert into Base31 SELECT '2', '2'
Insert into Base31 SELECT '3', '3'
Insert into Base31 SELECT '4', '4'
Insert into Base31 SELECT '5', '5'
Insert into Base31 SELECT '6', '6'
Insert into Base31 SELECT '7', '7'
Insert into Base31 SELECT '8', '8'
Insert into Base31 SELECT '9', '9'
Insert into Base31 SELECT 'B', '10'
Insert into Base31 SELECT 'C', '11'
Insert into Base31 SELECT 'D', '12'
Insert into Base31 SELECT 'F', '13'
Insert into Base31 SELECT 'G', '14'
Insert into Base31 SELECT 'H', '15'
Insert into Base31 SELECT 'J', '16'
Insert into Base31 SELECT 'K', '17'
Insert into Base31 SELECT 'L', '18'
Insert into Base31 SELECT 'M', '19'
Insert into Base31 SELECT 'N', '20'
Insert into Base31 SELECT 'P', '21'
Insert into Base31 SELECT 'Q', '22'
Insert into Base31 SELECT 'R', '23'
Insert into Base31 SELECT 'S', '24'
Insert into Base31 SELECT 'T', '25'
Insert into Base31 SELECT 'V', '26'
Insert into Base31 SELECT 'W', '27'
Insert into Base31 SELECT 'X', '28'
Insert into Base31 SELECT 'Y', '29'
Insert into Base31 SELECT 'Z', '30'

我正在尝试将这些主键转换为数值,但我一直在运行 int 限制。我已经更改了所有内容以使用大的 int 数据类型。如何获得使用大 int 数据类型的算术?

GO
CREATE Proc Base_31 @v varchar(8)

as    

DECLARE @Ai bigint
DECLARE @Bi bigint
DECLARE @Ci bigint
DECLARE @Di bigint
DECLARE @Ei bigint
DECLARE @Fi bigint
DECLARE @Gi bigint
DECLARE @Hi bigint

SELECT @Ai = NumberValue                 from Base31 where      RIGHT(@v,1)    = ID
SELECT @Bi = (NumberValue * POWER(31,1)) from Base31 where LEFT(RIGHT(@v,2),1) = ID
SELECT @Ci = (NumberValue * POWER(31,2)) from Base31 where LEFT(RIGHT(@v,3),1) = ID
SELECT @Di = (NumberValue * POWER(31,3)) from Base31 where LEFT(RIGHT(@v,4),1) = ID
SELECT @Ei = (NumberValue * POWER(31,4)) from Base31 where LEFT(RIGHT(@v,5),1) = ID
SELECT @Fi = (NumberValue * POWER(31,5)) from Base31 where LEFT(RIGHT(@v,6),1) = ID
SELECT @Gi = (NumberValue * POWER(31,6)) from Base31 where LEFT(RIGHT(@v,7),1) = ID
SELECT @Hi = (NumberValue * POWER(31,7)) from Base31 where LEFT(      @v   ,1) = ID

SELECT @v       AS Original
     , Cast(@Ai AS bigint) 
     + Cast(@Bi AS bigint) 
     + Cast(@Ci AS bigint) 
     + Cast(@Di AS bigint) 
     + Cast(@Ei AS bigint) 
     + Cast(@Fi AS bigint) 
     + Cast(@Gi AS bigint)
     + Cast(@Hi AS bigint) 
     as [Base 31 converted]
GO
4

2 回答 2

2

有更好的方法来做到这一点。以下方法适用于任意长度的数字和任意基数,只需稍作调整:

-- First convert a bigint to base-31 number string.
DECLARE @number bigint

SET @number = 123740194325432

DECLARE @Base31 table
(Digit varchar(1) NOT NULL,
 Value bigint NOT NULL PRIMARY KEY)

INSERT into @Base31 (Digit, Value) VALUES ('0', '0')
INSERT into @Base31 (Digit, Value) VALUES ('1', '1')
INSERT into @Base31 (Digit, Value) VALUES ('2', '2')
INSERT into @Base31 (Digit, Value) VALUES ('3', '3')
INSERT into @Base31 (Digit, Value) VALUES ('4', '4')
INSERT into @Base31 (Digit, Value) VALUES ('5', '5')
INSERT into @Base31 (Digit, Value) VALUES ('6', '6')
INSERT into @Base31 (Digit, Value) VALUES ('7', '7')
INSERT into @Base31 (Digit, Value) VALUES ('8', '8')
INSERT into @Base31 (Digit, Value) VALUES ('9', '9')
INSERT into @Base31 (Digit, Value) VALUES ('B', '10')
INSERT into @Base31 (Digit, Value) VALUES ('C', '11')
INSERT into @Base31 (Digit, Value) VALUES ('D', '12')
INSERT into @Base31 (Digit, Value) VALUES ('F', '13')
INSERT into @Base31 (Digit, Value) VALUES ('G', '14')
INSERT into @Base31 (Digit, Value) VALUES ('H', '15')
INSERT into @Base31 (Digit, Value) VALUES ('J', '16')
INSERT into @Base31 (Digit, Value) VALUES ('K', '17')
INSERT into @Base31 (Digit, Value) VALUES ('L', '18')
INSERT into @Base31 (Digit, Value) VALUES ('M', '19')
INSERT into @Base31 (Digit, Value) VALUES ('N', '20')
INSERT into @Base31 (Digit, Value) VALUES ('P', '21')
INSERT into @Base31 (Digit, Value) VALUES ('Q', '22')
INSERT into @Base31 (Digit, Value) VALUES ('R', '23')
INSERT into @Base31 (Digit, Value) VALUES ('S', '24')
INSERT into @Base31 (Digit, Value) VALUES ('T', '25')
INSERT into @Base31 (Digit, Value) VALUES ('V', '26')
INSERT into @Base31 (Digit, Value) VALUES ('W', '27')
INSERT into @Base31 (Digit, Value) VALUES ('X', '28')
INSERT into @Base31 (Digit, Value) VALUES ('Y', '29')
INSERT into @Base31 (Digit, Value) VALUES ('Z', '30')

DECLARE @base bigint
DECLARE @power bigint
DECLARE @divisor bigint
DECLARE @output varchar(50)
DECLARE @digit varchar(1)
DECLARE @digitValue bigint

SET @output = ''
SET @base = 31

IF @number < 0
BEGIN
    SET @number = ABS(@number)
    SET @output = '-'
END

IF NOT @number = 0
BEGIN   
    /* Due to the fact that the LOG10 function in SQL yields a float which limits the 
    available precision of the logarithm, numbers above 147209586032873 may have some 
    artifacts, i.e. LOG10(147209586032874) = LOG10(147209586032873). In actual practice, 
    I've found that numbers above 31^10 - 5 may manifest a leading zero when they are 
    near a power of 31, i.e. numbers in the ranges 31^10 - 4 to 31^10 - 1 and 
    31^11 - 158 to 31^11 - 1. */

    SET @power = FLOOR(LOG10(@number) / LOG10(@base))
END

WHILE @power >= 0 AND @number > 0
BEGIN
    SET @divisor = POWER(@base, @power)
    SET @digitValue = @number / @divisor
    SET @number = @number % @divisor

    SELECT @digit = Digit
    FROM @Base31
    WHERE Value = @digitValue

    SELECT @output = @output + @digit
    SET @power = @power - 1
END

SET @output = @output + COALESCE(REPLICATE('0', @power + 1), '0')

SELECT @output

-- Now convert the base-31 number string back to a bigint and see if we're right.
DECLARE @position bigint

SET @position = LEN(@output)
SET @number = 0

WHILE @position > 0
BEGIN
    SET @digit = SUBSTRING(@output, @position, 1)

    SELECT @digitValue = Value
    FROM @base31
    WHERE Digit = @digit

    SET @power = LEN(@output) - @position
    SET @number = @number + (@digitValue * POWER(@base, @power))
    SET @position = @position - 1
END

SELECT @number
于 2013-03-07T19:57:05.350 回答
2

问题是 POWER 函数返回与其第一个参数相同的类型。因此,您只需将第一个参数显式转换为 bigint。

此语句失败:

select power(31,7)

这个有效:

select power(cast(31 as bigint),7)
于 2013-03-07T18:38:16.987 回答