3

私たちのDBでは、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'

これらの主キーを数値に変換しようとしていますが、intint制限を実行し続けます。bigintデータ型を使用するようにすべてを変更しました。big 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

問題は、POWER関数が最初のパラメーターと同じ型を返すことです。したがって、最初のパラメータをbigintに明示的にキャストする必要があります。

このステートメントは失敗します:

select power(31,7)

そしてこれは機能します:

select power(cast(31 as bigint),7)
于 2013-03-07T18:38:16.987 に答える
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 に答える