sql-server - 如何匹配可变长度的子字符串?

标签 sql-server regex sql-server-2005

我正在将数据从 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 ,不建议在 joinon 子句中使用除列之外的任何内容。
原因是使用函数会阻止 sql server 在不使用函数时可能使用的列上使用任何索引。

因此,我建议在 imp 表中添加另一列,该列将保存实际的 ReceiptId 并在导入过程本身中进行计算。

我认为从 ref 列中提取 ReceiptId 的最佳方法是使用 substringpatindex ,如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

fiddle here

如果没有匹配,则返回 null, 当匹配是包含 A 后跟 4 或 5 个数字的子字符串时,与字符串的其余部分用空格分隔,并且可以在字符串的开头、中间或结尾找到。

关于sql-server - 如何匹配可变长度的子字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30319459/

相关文章:

sql-server - 历史、版本化和不可变数据

asp.net - 如何使用正则表达式判断字符串是否有 10 位数字?

c# - 使用 SqlConnection 打开 DataReader 错误

sql-server-2005 - 如何从 bat 文件远程运行 DTSX 包?

sql - 比较两个 SQL Server 数据库(架构和数据)的最佳工具是什么?

sql - 使用一个 SQL Server 查询从不同服务器上的不同数据库获取数据

regex - 如何在elasticsearch中编写正则表达式,以便为我提供带数字的URL?

regex - 带有非拉丁字符的 Golang 正则表达式

sql-server - 显示查询必须在 SQL Server 中运行多长时间

asp.net - LINQ 实体Where 子句位置不正确