用于查询SQL Server的正则表达式

时间:2019-03-20 20:41:15

标签: php sql-server laravel

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

这是一个示例:

寻求的数据:322211564

找到的数据:322'211'564

也322-211-564

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

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

2 个答案:

答案 0 :(得分:3)

一个通配符猜测,但这也许可行:

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函数。如果您随后改变主意,不想使用任何特殊字符,而需要使用&之类的可接受字符,则不会将其更改为&

答案 1 :(得分:0)

有关基于模式的字符串替换的注意事项,您可以使用SQL Server Regex之类的库。在您要转换的字符串上调用RegexReplace

select RegexReplace(col, '[^A-Za-z0-9]', '') from tbl

该呼叫将删除所有非字母数字字符。

要查找该列仅包含字母数字字符的所有行:

select col from tbl where col not like '%[^A-Za-z0-9]%'

like模式包括:

-匹配0个或更多字符。

[^ A-Za-z0-9] -匹配不在A-Z,a-z和0-9中的任何字符。字符类开头的^符号表示不匹配的字符。

通过使用not like,您的查询将拒绝在字符串中任何位置包含非字母数字字符的字符串。