Sql server 如何匹配可变长度的子字符串?
我正在将数据从Excel电子表格导入SQL数据库 imp表是导入的数据,app表是现有的数据库表 app.ReceiptId的格式为A,后跟一些数字。以前是4位数,但现在可能是4或5位数 示例:Sql server 如何匹配可变长度的子字符串?,sql-server,regex,sql-server-2005,Sql Server,Regex,Sql Server 2005,我正在将数据从Excel电子表格导入SQL数据库 imp表是导入的数据,app表是现有的数据库表 app.ReceiptId的格式为A,后跟一些数字。以前是4位数,但现在可能是4或5位数 示例: A1234 A9876 A10001 SHORT DESC A1234 - BZ-0987654321 LONGER DESCRIPTION A9876 - BZ-123 REALLY LONG DESCRIPTION A2345 - B REALLY REALLY LONG DESCRIPTION
A1234
A9876
A10001
SHORT DESC A1234 - BZ-0987654321
LONGER DESCRIPTION A9876 - BZ-123
REALLY LONG DESCRIPTION A2345 - B
REALLY REALLY LONG DESCRIPTION A23456
imp.ref是Excel中的自由文本引用字段。它包括一些任意长度的描述,然后是ReceiptId,然后是格式为-BZ-0987654321的不相关参考号,有时会缩短,甚至完全缺失
示例:
A1234
A9876
A10001
SHORT DESC A1234 - BZ-0987654321
LONGER DESCRIPTION A9876 - BZ-123
REALLY LONG DESCRIPTION A2345 - B
REALLY REALLY LONG DESCRIPTION A23456
下面的代码适用于4位数的ReceiptId,但不能正确捕获5位数的ReceiptId
UPDATE app
SET
[...]
FROM imp
INNER JOIN app
ON app.ReceiptId = right(right(rtrim(replace(replace(imp.ref,'-',''),'B','')),5)
+ rtrim(left(imp.ref,charindex(' - BZ-',imp.ref))),5)
如何更改代码以使其捕获4位A1234或5位A12345数字?如中所述,不建议在join的on子句中使用任何其他then列。
原因是使用函数会阻止sql server在不使用函数的情况下对列使用任何索引
因此,我建议在imp表中添加另一列,该列将保存实际的ReceiptId,并在导入过程中进行计算
我认为从ref列提取ReceiptId的最佳方法是使用with,如中所示:
更新
在评论中与t-clausen-dk对话后,我提出了以下观点:
SELECT ref,
CASE WHEN PATINDEX('%[ ]A[0-9][0-9][0-9][0-9][0-9| ]%', ref) > 0
OR PATINDEX('A[0-9][0-9][0-9][0-9][0-9| ]%', ref) = 1 THEN
SUBSTRING(ref, PATINDEX('%A[0-9][0-9][0-9][0-9][0-9| ]%', ref), 6)
ELSE
NULL
END As ReceiptId
FROM imp
如果没有匹配项,则返回null,
如果匹配项是一个子字符串,该子字符串包含一个后跟4或5位数字的数字,用空格与字符串的其余部分隔开,并且可以在字符串的开头、中间或结尾找到该子字符串。尝试此操作,它将删除a[number][number][number][number]前面的所有字符,并在其后保留前6个字符:
UPDATE app
SET
[...]
FROM imp
INNER JOIN app
ON app.ReceiptId in
(
left(stuff(ref,1, patindex('%A[0-9][0-9][0-9][0-9][ ]%', imp.ref + ' ') - 1, ''), 5),
left(stuff(ref,1, patindex('%A[0-9][0-9][0-9][0-9][0-9][ ]%', imp.ref + ' ') - 1, ''), 6)
)
使用equal时,后面的空格不计算能否提供一些示例数据?我想一些app.receiptid和imp.Ref就足够了。此外,如果A1234被视为等同于A12345?@ZoharPeled No,则每个接收方ID都是唯一的。我将添加一些示例数据,但我认为它描述得相当好。我建议在执行join时不要特别在sql中执行此操作。sql作为一种语言不适合ETL作业,更不用说字符串解析了。SQL Server为此提供SSI。您可以导入Excel数据,使用C脚本(可能带有正则表达式)解析列,并将数据输出到目标表。如果varchar为“A1234A”,则仍将认为它有效。如果您的varchar不包含有效数据,它将从第一个字符开始进行比较,您的RTRIM也是不必要的,如果varchar不包含有效数据,那么比较无论如何都会失败,但是感谢RTRIM的建议和最后一个空格,我将编辑我的答案以修复此问题。如果varcharREF以6个空格开始,并且它无效,然后,一旦您进行比较,并且ReceiptId中有许多空的varchar,您将更新它们allExample以说明将返回一行:SELECT RTRIMSUBSTRINGref,PATINDEX“%a[0-9][0-9][0-9][0-9]”,ref,6 FROM SELECT''ref x WHERE ref=@t-clausen.dk查看我编辑的答案。感谢您查找缺陷,它帮助我改进sql。