1

我只是想知道在 SQL Server 2005 中是否有更好的方法来执行此操作。

实际上,我使用了一个 originator_id(0 到 99 之间的数字)和一个“next_element”(它实际上只是一个 1 到 999,999 之间的顺序计数器)。我们正在尝试从它们中创建一个 6 字符的“代码”。

originator_id 乘以一百万,然后加上计数器,得到一个介于 0 和 99,999,999 之间的数字。

然后我们将其转换为“base 32”字符串 - 一个假的 base 32,我们实际上只是使用 0-9 和 AZ,但为了清楚起见,删除了一些更令人困惑的字母数字(I、O、S、Z) .

为此,我们只需将数字除以 32 的幂,在每个阶段使用我们为每个幂得到的结果作为我们所选字符数组中字符的索引。

因此,61 的发起者 ID 和 9 的 NextCodeElement 给出的代码为“1T5JA9”

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

所以我的代码是 1T5JA9

以前我已经让这个算法工作(在 Delphi 中),但现在我真的需要能够在 SQL Server 2005 中重新创建它。显然我没有与 Delphi 中相同的功能,但这是我的采取例行公事。它可以工作,我可以很好地生成代码(或将代码重构回它们的组件)。

但它看起来有点啰嗦,而且我不确定将除法结果选择为 int 的技巧(即,真的是强制转换)是否一定是“正确的”——这种方法是否有更好的 SQLS 方法的东西?

CREATE 过程 dummy_RP_CREATE_CODE @NextCodeElement int, @OriginatorID int,
  @code varchar(6) 输出
作为
开始
  声明@raw_num int;
  声明@bcelems char(32);
  声明@chr int;

  选择@bcelems='0123456789ABCDEFGHJKLMNPQRTUVWXY';
  选择@code='';

  -- 添加originator_id,缩放到位
  选择@raw_num = (@OriginatorID * 1000000) + @NextCodeElement;

  -- 现在将其转换为 6 字符代码

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

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

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

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

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

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

  -  就是这样!
结尾;

我并不非常关心优化,除非这种方法实际上比任何替代方法都差一个数量级(或更多)。

代码只会以小批量的方式执行,可能每 10 分钟左右生成 20 或 30 个代码。由于数字范围很大,我不想将代码预先计算到一个巨大的表格中(在任何给定的安装中,只会使用整个代码范围的一小部分)。

但是,我确信可能有一种更简洁的方法可以实现相同的结果——尤其是那些除法和减法。

任何建设性的批评、意见或建议都将受到欢迎。

4

2 回答 2

3

看到它是 SQL Server 2005,有什么理由不使用 CLR 存储过程?您可以使用您选择的 CLR 语言,它可能是您现有 Delphi 代码的相对直接的端口。

于 2008-09-10T23:44:26.123 回答
0

虽然它可以在 SQL Server 2005 中清楚地完成,但我认为某种预编译的高级语言例程具有足够的“非数据库性”是有意义的。

我为 Interbase/Firebird 编写了 DLL,为 SQL Server 编写了 T-SQL 存储过程,但从未编写过 CLR 例程。这将是一个有趣的练习!

于 2008-09-11T11:25:26.857 回答