t-sql - 如何在T-SQL中匹配US-ASCII字符?

标签 t-sql ascii sql-like

我想将 URL 存储在列中。根据RFC 3986 , US-ASCII 是组成 URL 的字符集。

SQL Server 具有 VARCHAR 类型,它可以对 US-ASCII 字符集中的所有字符以及依赖于代码页的 128 个字符进行编码。

我想使用 CHECK 约束来确保列中的值仅包含 US-ASCII 字符集中的可打印字符;换句话说,ASCII(@char) >= 32 AND ASCII(@char) < 127对于字符串中的每个字符。

我认为我可以使用 LIKE 表达式在检查约束中执行此操作,但我找不到正确的模式。我正在尝试采用 Itzik Ben-Gan 的技巧,即匹配允许范围之外的任何字符,他在文章 Can I convert this string to an integer? 中介绍了这一技巧。 .

在我的测试工具中,我创建了一个表 @TestData插入我的列(表格)的候选人 @Patterns与 LIKE 运算符一起使用的模式,然后选择每个模式与每个候选者的匹配结果:

DECLARE @TestData TABLE (
  String VARCHAR(60) COLLATE Latin1_General_CI_AS NOT NULL
);

INSERT INTO @TestData(String)
VALUES
  ('€ÿ'),
  ('ab3'),
  ('http://www.google.com/'),
  ('http://www.example.com/düsseldorf?neighbourhood=Lörick'),
  ('1234');

DECLARE @Patterns TABLE (
  Pattern VARCHAR(12) COLLATE Latin1_General_CI_AS NOT NULL
);

INSERT INTO @Patterns (Pattern)
VALUES
  ('%[^0-9]%'),
  ('%[^' + CHAR(32) + '-' + CHAR(126) + ']%');

SELECT
  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ID,
  String,
  Pattern,
  CASE WHEN String NOT LIKE Pattern THEN 1 ELSE 0 END AS [Match]
FROM @TestData CROSS JOIN @Patterns;

第一行插入 @Patterns就像 Itzik 用于匹配非数字字符的模式。第二行是我尝试针对可打印 US-ASCII 字符范围之外的字符进行调整。

当我执行上述批处理时,我收到以下结果集:

ID   String                                                   Pattern      Match
---  -------------------------------------------------------- ------------ ------
 1    €ÿ                                                       %[^0-9]%     0
 2    ab3                                                      %[^0-9]%     0
 3    http://www.google.com/                                   %[^0-9]%     0
 4    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^0-9]%     0
 5    1234                                                     %[^0-9]%     1
 6    €ÿ                                                       %[^ -~]%     0
 7    ab3                                                      %[^ -~]%     0
 8    http://www.google.com/                                   %[^ -~]%     0
 9    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^ -~]%     0
 10   1234                                                     %[^ -~]%     0

正如预期的那样,第 5 行是匹配项,因为候选值仅包含数字。第 1 行到第 4 行中的候选值不仅仅包含数字,因此与模式不匹配。

正如预期的那样,第 6 行中的候选字符与模式不匹配,因为它包含“高位 ASCII”字符。

我希望第 7、8 和 10 行中的候选字符能够匹配,因为它们仅包含可打印的 US-ASCII 字符。但这些不匹配。

LIKE 表达式中的模式有什么问题?

最佳答案

正如问题评论和 similar question 的答案中所建议的那样,我需要使用二进制排序规则子句。

如果我将选择语句更改为:

SELECT
  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ID,
  String,
  Pattern,
  CASE WHEN String NOT LIKE Pattern COLLATE Latin1_General_BIN THEN 1 ELSE 0 END AS [Match]
FROM @TestData CROSS JOIN @Patterns;

我得到以下结果集:

ID   String                                                   Pattern      Match
---  -------------------------------------------------------- ------------ ------
 1    €ÿ                                                       %[^0-9]%     0
 2    ab3                                                      %[^0-9]%     0
 3    http://www.google.com/                                   %[^0-9]%     0
 4    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^0-9]%     0
 5    1234                                                     %[^0-9]%     1
 6    €ÿ                                                       %[^ -~]%     0
 7    ab3                                                      %[^ -~]%     1
 8    http://www.google.com/                                   %[^ -~]%     1
 9    http://www.example.com/düsseldorf?neighbourhood=Lörick   %[^ -~]%     0
 10   1234                                                     %[^ -~]%     1

现在“匹配”列包含预期值。

关于t-sql - 如何在T-SQL中匹配US-ASCII字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10753205/

相关文章:

sql - 按一列对重复项进行分组,但显示另一列

c - 从 C 文件中读取 ASCII 字符

c - 如何使用 XCode 以 C 语言输出笑脸

mysql - 在整个Mysql表(所有字段)中搜索特定字符串

MySQL - 需要在 URL 表中搜索包含指定单词的 URL

php - Laravel - LIKE 运算符来搜索加密值

t-sql - 一列拆分为更多列sql server 2008?

SQL 通过连接表从其他表中选择总和作为列

t-sql - 如何在不对行数据进行分组的情况下将总计/小计添加到一组结果中?

windows-10 - 是否有一个 ASCII 箭头可以与方框图字符无缝匹配?