匹配SQL Server表中具有可变数量的前导零的字段

时间:2010-02-05 18:31:17

标签: sql-server database tsql

我遇到的情况是我有一个输入数据值,可能有也可能没有前导零。我需要将它与SQL Server表中的字段/行匹配。 SQL Server数据库中的字段值可能也可能没有前导零。

所以,我可能会:

  • 来电= 5042800138
    db中的值可以是5042800138,05042800138,005042800138,0005042800138

  • 中的任何一个
  • 或来电可能是005042800138
    db中的值可以是5042800138,05042800138,005042800138,0005042800138

  • 中的任何一个

我提出的解决方案是删除传入数据的前导零(总是)并使用SQL,如下例所示:

-- this simulates the incoming value to check
-- i strip out the leading zeroes.
declare @tryUPC as varchar(40)
set @tryUPC = '5042800138'

-- try to find it in the database and ignore leading zeroes
select prod_uid, prod_partno, prod_upc
from products as p
where (prod_upc = @tryUPC) or 
   (
   len(prod_upc) > len(@tryUPC)
   and right(prod_upc, len(@tryUPC)) = @tryUPC
   and stuff(prod_upc, 1, len(prod_upc) - len(@tryUPC), '0') = prod_upc
   )

这似乎有效。我的问题是,我错过了什么吗? SQL Server有更好的方法来解决这个问题吗?我正在使用SQL Server 2005。

tia,

3 个答案:

答案 0 :(得分:4)

只是另一个倾斜(纠正数据将是最好的,但接受的答案也是一个不错的解决方法):添加一个持久的,索引的计算列“actualUPC”,这是一个字符类型,使用正确的前导零数计算。例如:

如果“真实”代码应该是12位数,请创建一个像

这样的计算列
 right( '000000000000' + originalColumn, 12 )

这样输入数据实际上得到了纠正,然后正确编入索引并可以用索引进行搜索。

查询时,还要输出要匹配的输入,作为查询中的常量。

检查对索引计算列的限制,然后再过于疯狂。

像这样的BTW代码(邮政编码,序列号,ssn等)应始终存储为文本数据,前导零,永不作为整数或数字类型。从一个以邮政编码01033长大的人那里拿走。

答案 1 :(得分:2)

如果您无法更改现有数据以去除前导零/转换为INT,那么执行以下操作可能会更快:

WHERE prod_upc IN (@tryUPC, '0' + @tryUPC, '00' + @tryUPC, '000' + @tryUPC [...])

那就像我的脚一样优雅,但它会更加静止&清晰易读,并且(可能)更有可能获得任何相关指数。

假设对你有多少前导零有一个有限的限制,请注意。将数据转换为INT(或添加新的INT列并在插入时计算它)可能是解决问题的最佳方法。

答案 2 :(得分:0)

1)更新所有现有数据,使其不具有任何前导零,可能使用BIGINT数据类型 2)在保存和搜索之前,始终从输入中删除前导零 3)再也不用担心领先零了,你实际上可以使用索引!

修改 在OP的评论之后:

不是很好,但它不是现实。我想我应该提到这是一个遗留应用程序。 upc代码可以在一堆不同的地方输入。更改数据类型需要大量的refractoring。此外,有时需要零 - 有一个很好的理由使数据库成为它的方式。 - 唐迪金森

您可以使用持久计算列来REVERSE()列,然后将其编入索引。然后你可以查询:

WHERE Column1Reverse Like REVERSE('1234567')+'%' --can use the persistent computed column's index

添加一个持久计算列(反转字符串)并对其进行索引,请使用以下代码:

ALTER TABLE YourTable ADD ReversedYourString AS REVERSE(YourString)PERSISTED

CREATE NONCLUSTERED INDEX IX_YourTable_ReversedYourString 
ON YourTable (ReversedYourString)