我在应用程序中具有到外部表的SQL Server连接,我需要进行查询,其中一列的格式错误,例如,格式为无符号的字母数字,但列中的数据带有破折号,撇号,点,你叫它。是否可以只查询已过滤掉的列之一?真的对我有帮助。我正在使用Laravel,我知道我可以创建一个访问器来清除它,但查询很繁重。
这是一个示例:
寻求的数据:322211564
找到的数据:322'211'564
也322-211-564
编辑:只是为了澄清,我不想排除数据,而是要在不使用符号的情况下“重新格式化”它。
编辑:顺便说一句,如果您对使用Laravel 5.7感到好奇,则可以直接查询访问器(如果您已经拥有该集合)。我很惊讶,但是能成功。
答案 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
,您的查询将拒绝在字符串中任何位置包含非字母数字字符的字符串。