首页 > 解决方案 > 用于查询 SQL Server 的正则表达式

问题描述

我的应用程序中有一个到外部表的 SQL Server 连接,我需要查询其中一个列的格式错误,比如说,格式是不带符号的字母数字,但该列的数据带有破折号、撇号、点,你的名字。是否可以只查询过滤掉的列之一?它真的对我有帮助。我正在使用 Laravel,我知道我可以制作一个访问器来清除它,但是查询很繁重。

这是一个例子:

求资料:322211564

找到的数据:322'211'564

还有 322-211-564

编辑:只是为了澄清,我不想排除数据,而是要“重新格式化”它而不使用符号。

编辑:顺便说一句,如果您对使用 Laravel 5.7 感到好奇,显然您可以直接查询访问器(如果您已经拥有该集合)。我很惊讶,但它确实有效。

标签: phpsql-serverlaravel

解决方案


一个外卡猜测,但也许这有效:

WITH VTE AS(
    SELECT *
    FROM (VALUES('322''211''564'),
                ('322-211-564')) V(S))
SELECT S,
       (SELECT '' + token
        FROM dbo.NGrams8k(V.S,1) N
        WHERE token LIKE '[A-z0-9]'
        ORDER BY position
        FOR XML PATH('')) AS S2
FROM VTE V;

这利用了该NGrams8k功能。如果您需要其他可接受的字符,您可以简单地将它们添加到模式字符串 ( '[A-z0-9]') 中。

如果由于某种原因您不想使用NGrams8k,您可以创建一个内联计数表,该表将执行类似的功能:

WITH N AS(
    SELECT N
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1 --10
         CROSS JOIN N N2 --100
         CROSS JOIN N N3 --1000
         CROSS JOIN N N4 --10000 --Do we need any more than that? You may need less
    ),
VTE AS(
    SELECT *
    FROM (VALUES('322''211''564'),
                ('322-211-564')) V(S))    
SELECT V.S,
       (SELECT '' + SS.C
        FROM Tally T
             CROSS APPLY (VALUES(SUBSTRING(V.S,T.I,1))) SS(C)
        WHERE SS.C LIKE '[A-z0-9]'
        ORDER BY T.I
        FOR XML PATH(''),TYPE).value('.','varchar(8000)') AS S2
FROM VTE V;

另外,以防万一,我使用了TYPE格式和value功能。如果您随后改变主意不想要任何特殊字符并需要一个可接受的字符,例如&,它不会更改为&.


推荐阅读