我正在将数据从 Excel 电子表格导入到 SQL 数据库中。
imp
表是导入的数据,app
表是现有的数据库表。
app.ReceiptId
的格式为“A”后跟一些数字。以前是4位,现在可能是4位、5位。
示例:
A1234
A9876
A10001
imp.ref
是 Excel 中的自由文本引用字段。它由一些任意长度的描述组成,然后是 ReceiptId,后跟格式为“-BZ-0987654321”的不相关引用号(有时会被剪短,甚至完全丢失)。
示例:
SHORT DESC A1234 - BZ-0987654321
LONGER DESCRIPTION A9876 - BZ-123
REALLY LONG DESCRIPTION A2345 - B
REALLY REALLY LONG DESCRIPTION A23456
下面的代码适用于 4 位 ReceiptId
,但无法正确捕获 5 位数字。
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) 位数字?
最佳答案
如ughai正确地写在 his comment ,不建议在 join
的 on
子句中使用除列之外的任何内容。
原因是使用函数会阻止 sql server 在不使用函数时可能使用的列上使用任何索引。
因此,我建议在 imp 表中添加另一列,该列将保存实际的 ReceiptId
并在导入过程本身中进行计算。
我认为从 ref
列中提取 ReceiptId
的最佳方法是使用 substring
与 patindex
,如this fiddle中所示:
SELECT ref,
RTRIM(SUBSTRING(ref, PATINDEX('%A[0-9][0-9][0-9][0-9]%', ref), 6)) As ReceiptId
FROM imp
更新
在评论中与 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, 当匹配是包含 A 后跟 4 或 5 个数字的子字符串时,与字符串的其余部分用空格分隔,并且可以在字符串的开头、中间或结尾找到。
关于sql-server - 如何匹配可变长度的子字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30319459/