使用特殊字符检查字符串是否有效
Checking if a string is valid with special chars
我正在使用 PATINDEX
来验证列是否包含无效的特殊字符。但是我遇到了一些字符问题。
SELECT PATINDEX(N'%[^a-zA-Z0-9 !"&''()*+,-./:;?=%~@[]_{}\|<>]%' collate SQL_Latin1_General_CP850_BIN, 'abc╢123' collate SQL_Latin1_General_CP850_BIN)
有效字符为 ! " & ' ( ) * + , - . / : ; ? = % ~ @ [ ] _ { } \ | < >
。
╢
不是有效字符之一,但 PATINDEX 仍然是 returns 0。
还有其他验证方法吗?
问题似乎是由模式中的 ]
引起的。您可以将 LIKE
运算符与 ESCAPE
一起使用。最小示例:
-- valid characters are digits, "[" and "]"
SELECT val
, expected
, CASE WHEN val LIKE '%[^0-9[]]%' THEN 'Bad' ELSE 'Good' END AS wrong_pattern
, CASE WHEN val LIKE '%[^0-9[\]]%' ESCAPE '\' THEN 'Bad' ELSE 'Good' END AS right_pattern
FROM (VALUES
('12345', 'Good'),
('[123]', 'Good'),
('ABCDE', 'Bad'),
('123', 'Bad')
) AS t(val, expected)
所以你的模式可以写成:
SELECT CASE WHEN 'abc╢123!"&''()*+,-./:;?=%~@[]_{}\|<>' NOT LIKE '%[^a-z0-9 [\]\!"&''()*+,\-./:;?=%~@_{}|<>]%' ESCAPE '\' THEN 'Good' ELSE 'Bad' END
我逃脱了 ]
、-
和 \
。字符 %
和 _
在方括号内不作为通配符,因此不会转义。
转义是一种方法。
但是,如果您只想忽略可读的 ASCII 字符,则可以简化范围。
[^ -~]
:不在 space 和 ~
之间
-- Sample data
declare @T table (col NVARCHAR(30) collate SQL_Latin1_General_CP850_BIN primary key);
insert into @T (col) values
(N'abc╢123'),
(N'xyz123[}'''),
(N'abc௹123');
-- Query
SELECT col, PATINDEX(N'%[^ -~]%' collate SQL_Latin1_General_CP850_BIN, col) as pos
FROM @T;
Returns:
col pos
-------- ----
abc╢123 4
abc௹123 4
xyz123[}' 0
但要同时定位插入符号和其他一些,则比较复杂。
因为 PATINDEX 不像 LIKE 那样有 ESCAPE。
-- Sample data
declare @T table (
id int identity(1,1) primary key,
col NVARCHAR(30) collate SQL_Latin1_General_CP850_BIN
);
insert into @T (col) values
(N'xyz[123]}''') -- good
,(N'abc╢123') -- bad
,(N'abc௹123') -- bad
,(N'def#456') -- bad
,(N'def^456') -- bad
;
-- also locate #, ´ , ` and ^
SELECT col,
CASE
WHEN PATINDEX(N'%[^ !"$-_a-z{-~]%' collate SQL_Latin1_General_CP850_BIN, col) > 0
THEN PATINDEX(N'%[^ !"$-_a-z{-~]%' collate SQL_Latin1_General_CP850_BIN, col)
ELSE CHARINDEX(N'^' collate SQL_Latin1_General_CP850_BIN, col)
END AS pos
FROM @T;
Returns:
xyz[123]}' 0
abc╢123 4
abc௹123 4
def#456 4
def^456 4
我正在使用 PATINDEX
来验证列是否包含无效的特殊字符。但是我遇到了一些字符问题。
SELECT PATINDEX(N'%[^a-zA-Z0-9 !"&''()*+,-./:;?=%~@[]_{}\|<>]%' collate SQL_Latin1_General_CP850_BIN, 'abc╢123' collate SQL_Latin1_General_CP850_BIN)
有效字符为 ! " & ' ( ) * + , - . / : ; ? = % ~ @ [ ] _ { } \ | < >
。
╢
不是有效字符之一,但 PATINDEX 仍然是 returns 0。
还有其他验证方法吗?
问题似乎是由模式中的 ]
引起的。您可以将 LIKE
运算符与 ESCAPE
一起使用。最小示例:
-- valid characters are digits, "[" and "]"
SELECT val
, expected
, CASE WHEN val LIKE '%[^0-9[]]%' THEN 'Bad' ELSE 'Good' END AS wrong_pattern
, CASE WHEN val LIKE '%[^0-9[\]]%' ESCAPE '\' THEN 'Bad' ELSE 'Good' END AS right_pattern
FROM (VALUES
('12345', 'Good'),
('[123]', 'Good'),
('ABCDE', 'Bad'),
('123', 'Bad')
) AS t(val, expected)
所以你的模式可以写成:
SELECT CASE WHEN 'abc╢123!"&''()*+,-./:;?=%~@[]_{}\|<>' NOT LIKE '%[^a-z0-9 [\]\!"&''()*+,\-./:;?=%~@_{}|<>]%' ESCAPE '\' THEN 'Good' ELSE 'Bad' END
我逃脱了 ]
、-
和 \
。字符 %
和 _
在方括号内不作为通配符,因此不会转义。
转义是一种方法。
但是,如果您只想忽略可读的 ASCII 字符,则可以简化范围。
[^ -~]
:不在 space 和 ~
-- Sample data
declare @T table (col NVARCHAR(30) collate SQL_Latin1_General_CP850_BIN primary key);
insert into @T (col) values
(N'abc╢123'),
(N'xyz123[}'''),
(N'abc௹123');
-- Query
SELECT col, PATINDEX(N'%[^ -~]%' collate SQL_Latin1_General_CP850_BIN, col) as pos
FROM @T;
Returns:
col pos
-------- ----
abc╢123 4
abc௹123 4
xyz123[}' 0
但要同时定位插入符号和其他一些,则比较复杂。
因为 PATINDEX 不像 LIKE 那样有 ESCAPE。
-- Sample data
declare @T table (
id int identity(1,1) primary key,
col NVARCHAR(30) collate SQL_Latin1_General_CP850_BIN
);
insert into @T (col) values
(N'xyz[123]}''') -- good
,(N'abc╢123') -- bad
,(N'abc௹123') -- bad
,(N'def#456') -- bad
,(N'def^456') -- bad
;
-- also locate #, ´ , ` and ^
SELECT col,
CASE
WHEN PATINDEX(N'%[^ !"$-_a-z{-~]%' collate SQL_Latin1_General_CP850_BIN, col) > 0
THEN PATINDEX(N'%[^ !"$-_a-z{-~]%' collate SQL_Latin1_General_CP850_BIN, col)
ELSE CHARINDEX(N'^' collate SQL_Latin1_General_CP850_BIN, col)
END AS pos
FROM @T;
Returns:
xyz[123]}' 0
abc╢123 4
abc௹123 4
def#456 4
def^456 4