SQL Server の「エンコーディング」sproc をカスタマイズする - これを行うより適切な方法はありますか?

StackOverflow https://stackoverflow.com/questions/55340

  •  09-06-2019
  •  | 
  •  

質問

SQL Server 2005 でこれを行うより良い方法があるかどうか疑問に思っています。

実際には、originator_id (0 から 99 までの数値) と 'next_element' (実際には 1 から 999,999 までの単なる連続カウンター) を取得します。私たちはそれらから 6 文字の「コード」を作成しようとしています。

originator_id に 100 万を掛けてからカウンターを加算すると、0 ~ 99,999,999 の数値が得られます。

次に、これを「基数 32」文字列、つまり偽の基数 32 に変換します。実際には 0 ~ 9 と A ~ Z を使用しているだけですが、わかりやすくするためにいくつかの混乱を招く英数字 (I、O、S、Z) が削除されています。 。

これを行うには、各段階で、選択した文字の配列からの文字のインデックスとして各累乗で得られた結果を使用して、数値を 32 の累乗で除算するだけです。

Thus, an originator ID of 61 and NextCodeElement of 9 gives a code of '1T5JA9'

(61 * 1,000,000) + 9 = 61,000,009
61,000,009 div (5^32 = 33,554,432) =  1 = '1'
27,445,577 div (4^32 =  1,048,576) = 26 = 'T'
   182,601 div (3^32 =     32,768) =  5 = '5'
    18,761 div (2^32 =      1,024) = 18 = 'J'
       329 div (1^32 =         32) = 10 = 'A'
         9 div (0^32 =          1) =  9 = '9'

so my code is 1T5JA9

以前はこのアルゴリズムを (Delphi で) 動作させていましたが、今度は SQL Server 2005 で再作成できるようにする必要があります。もちろん、Delphi と同じ関数を私が手元に持っているわけではありませんが、これがルーチンに対する私の見解です。それは機能し、コードを生成する(またはコードをコンポーネントに再構築する)ことができます。

しかし、それは少し長そうですし、int への除算の結果を選択する (つまり、実際にキャストする) トリックが必ずしも「正しい」かどうかはわかりません。この種に対するより良い SQLS アプローチはありますか?ことの?

CREATE procedure dummy_RP_CREATE_CODE @NextCodeElement int, @OriginatorID int,
  @code varchar(6) output
as
begin
  declare @raw_num int;
  declare @bcelems char(32);
  declare @chr int;

  select @bcelems='0123456789ABCDEFGHJKLMNPQRTUVWXY';
  select @code='';

  -- add in the originator_id, scaled into place
  select @raw_num = (@OriginatorID * 1000000) + @NextCodeElement;

  -- now to convert this to a 6-char code

  -- 5^32
  select @chr = @raw_num / 33554432;
  select @raw_num = @raw_num - (@chr * 33554432);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 4^32
  select @chr = @raw_num / 1048576;
  select @raw_num = @raw_num - (@chr * 1048576);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 3^32
  select @chr = @raw_num / 32768;
  select @raw_num = @raw_num - (@chr * 32768);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 2^32
  select @chr = @raw_num / 1024;
  select @raw_num = @raw_num - (@chr * 1024);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 1^32
  select @chr = @raw_num / 32;
  select @raw_num = @raw_num - (@chr * 32);
  select @code = @code + SUBSTRING(@bcelems, 1 + @chr, 1);

  -- 0^32  
  select @code = @code + SUBSTRING(@bcelems, 1 + @raw_num, 1);

  -- that's it!
end;

この方法が実際に他の方法よりも 1 桁 (またはそれ程度) 悪い場合を除き、最適化についてはそれほど心配していません。

コードは小さなバーストでのみ実行され、おそらく 10 分ごとに 20 ~ 30 個のコードが生成されます。数値の範囲が広いため、コードを事前に計算して巨大なテーブルを作成することは望ましくありません (特定のインストールでは、コード範囲全体の小さな部分のみが使用されます)。

ただし、同じ結果、特に割り算と引き算を達成するための、おそらくもっと整った方法があるはずです。

建設的な批判、観察、提案は大歓迎です。

役に立ちましたか?

解決

SQL Server 2005 であるのに、CLR ストアド プロシージャを使用しない理由はありますか?その場合、選択した CLR 言語を使用することができ、おそらく既存の Delphi コードの比較的直接的な移植となるでしょう。

他のヒント

これは明らかに SQL Server 2005 でも実行できますが、プリコンパイルされた高級言語ルーチンのようなものを使用するのは十分に「非データベース性」があると思います。

私は Interbase/Firebird 用の DLL と SQL Server 用の T-SQL sproc を作成したことがありますが、CLR ルーチンを作成したことはありません。面白い練習になるでしょう!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top