检查 VARCHAR 字段是否包含非 Ascii 字符的最佳方法是什么?
CHAR(1)
彻头彻尾。CHAR(31)
CHAR(127)
CHAR(255)
我尝试使用PATINDEX
并遇到了以下问题。
检查较低的范围工作正常。
SELECT *
FROM mbrnotes
WHERE PATINDEX('%[' + CHAR(1)+ '-' +CHAR(31)+']%',LINE_TEXT) > 0
我的数据有 0x1E 的三个记录,所有三个都返回了。
但是当我只检查上限时:
SELECT *
FROM mbrnotes
WHERE PATINDEX('%[' + CHAR(127)+ '-' +CHAR(255)+']%',LINE_TEXT) > 0
它返回接近表中的所有记录(表计数 170737 并返回计数 170735),并且由于我的数据在此范围内没有任何值,我认为它应该没有返回任何记录。
模式语法中的范围使用排序规则的排序规则。
使用二进制整理子句,以便范围按字符代码排序。
(我也将其更改为,LIKE
因为我发现它比 更明显PATINDEX > 0
)
SELECT *
FROM mbrnotes
WHERE LINE_TEXT COLLATE Latin1_General_100_BIN2
LIKE '%[' + CHAR(0)+ '-' +CHAR(31) + CHAR(127)+ '-' +CHAR(255)+']%'
如果您真的想查看有问题的字符并且您使用的是具有该TRANSLATE
功能的版本,您可以使用类似下面的内容
DECLARE @WhiteListedCharacters NVARCHAR(1000)
= ' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ '[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
SELECT text,
REPLACE(
TRANSLATE(
text,
@WhiteListedCharacters COLLATE Latin1_General_100_BIN2,
REPLICATE(
LEFT(@WhiteListedCharacters,1),
LEN(@WhiteListedCharacters))),
LEFT(@WhiteListedCharacters,1),
'') AS BadChars
FROM sys.messages
WHERE language_id = 1038
然后,您可以在第二次调用中使用该结果TRANSLATE
来仅保留“好”字符。
DECLARE @WhiteListedCharacters NVARCHAR(1000)
= ' !"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ '[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
SELECT text,
BadChars,
Cleaned = REPLACE(
TRANSLATE(
text COLLATE Latin1_General_100_BIN2,
BadChars,
REPLICATE(N'ψ', LEN(BadChars))
),
N'ψ', N'')
FROM sys.messages
CROSS APPLY
(
SELECT REPLACE(
TRANSLATE(
text,
@WhiteListedCharacters COLLATE Latin1_General_100_BIN2,
REPLICATE(
LEFT(@WhiteListedCharacters,1),
LEN(@WhiteListedCharacters + '-') - 1)),
LEFT(@WhiteListedCharacters,1),
'') AS BadChars
) ca
WHERE language_id = 1038