定制的SQL Server"编码"存储过程-是否有更整洁的方式做到这一点?
我只是想知道在SQL Server 2005中是否有更好的方法可以做到这一点。
实际上,我正在使用一个originator_id(一个介于0和99之间的数字)和一个" next_element"(实际上只是一个介于1和999,999之间的顺序计数器)。
我们正在尝试从中创建一个6个字符的"代码"。
将originator_id乘以一百万,然后将计数器相加,得到一个介于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;
除非此方法实际上比其他方法差一个数量级(或者大约一个数量级),否则我并不急于优化。
该代码只会被执行一小段,可能每10分钟左右生成20或者30个代码。由于数字范围很大,因此我不想将代码预先计算到一个巨大的表中(在任何给定的安装中都只会使用整个代码范围的一小部分)。
但是,我敢肯定,有一种更整齐的方法可以达到相同的结果,尤其是那些除法和减法。
任何建设性的批评,意见或者建议都将受到欢迎。
解决方案
回答
看到它是SQL Server 2005,是否有理由不使用CLR存储过程?然后,我们可以使用选择的CLR语言,并且它可能是现有Delphi代码的相对直接端口。
回答
尽管可以在SQL Server 2005中很明显地做到这一点,但我认为它具有足够的"非数据库性",某种预编译的高级语言例程才有意义。
我已经为Interbase / Firebird编写了DLL,为SQL Server编写了T-SQL sproc,但从未编写CLR例程。这将是一个有趣的练习!