在我们的数据库中,我们使用主键来表示数字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数据类型。如何让算术使用大型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
答案 0 :(得分:2)
问题是POWER函数返回与第一个参数相同的类型。所以你只需要将第一个参数显式地转换为bigint。
此声明失败:
select power(31,7)
这个有效:
select power(cast(31 as bigint),7)
答案 1 :(得分: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