任意の基数の文字列を整数値に変換するユーザー定義関数

恥ずかしながら、再帰CTEを知らずに、

をセンス無いと酷評して、渦巻きな人とちょっと喧嘩気味になっちゃいましたが、再利用性を考慮して個人的にはユーザ定義関数で実装しておきます。

ユーザー定義関数の実装は

無難にこんな感じですかね。SUBSTRING関数よりもCASE式の方がCPU負荷が軽そうですが、煩雑なのでズボラしました。

CREATE FUNCTION [dbo].[STRTONUM](@number_string varchar(64), @radix int)
RETURNS int
AS
BEGIN
  DECLARE @digits varchar(64);  SET @digits = UPPER(@number_string)
  DECLARE @N int;               SET @N = LEN(@digits)
  DECLARE @value int;           SET @value = 0
  DECLARE @i int;               SET @i = 1
  WHILE @i <= @N
  BEGIN
    DECLARE @digit int
    SET @digit = CHARINDEX(SUBSTRING(@digits, @i, 1), '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ')
    IF @digit = 0 RETURN @value
    SET @value = @value * @radix + (@digit - 1)
    SET @i = @i + 1
  END
  RETURN @value
END

使い方は

こんな感じです。その基数表記で不正な文字に出くわしたら、数値としての評価を中止します*1

SELECT dbo.STRTONUM('FFFF!', 16)

けどね、何でこんな関数が処理系標準じゃないのか、一度考察しておこう

DBサーバをスケールアウトするようにシステムを実装するのは大変なのが、ふつー。
中小企業のシステムではDBサーバが1台のみとか平気であるし*2
だから、DBサーバには極力負荷を掛けたくない。故にこんな変態なデータはintとかbigintとかimageとかで格納しておくのがふつー。
つまり、DBエンジンNativeなデータ型に変換するのはスケールアウトが楽なWebサーバのお仕事。


結論:こんなしょーもない仕事はフロントエンドでやっておけ
と言う事で、M$の中の人は敢えてCONVERT関数の中にこんな機能を実装しなかったと妄想しておく。

じゃ、何でわざわざお前は実装したのさ?

id:babydaemonsが変態だから!*3というのは置いといて、今回のお仕事のフロントエンドはよりによって


レガシーASP(VBScript)なんですよ!
そんな変態言語でこんなやっつけ仕事をやるよりも、まだTransact-SQLで書いたほうがマトモだったので消去法で選択しただけです。orz

*1:C言語のstrtol(3)と同じ。

*2:ハードウェアもさることながら、ライセンスコストが企業体力的に耐えられない。だったら、MySQLとか使えよw あ、バックアップはやってるけどね。

*3:いや、否定はしませんが。。。