【问题标题】:Case sensitivity check constraint with LIKE operator using character range wildcards使用字符范围通配符的 LIKE 运算符的区分大小写检查约束
【发布时间】:2015-04-14 00:16:24
【问题描述】:

我遇到了正则表达式区分大小写的问题。在正则表达式中,只有第一项在方括号内有效。

create table
(
    FlowerId varchar(7)

    constraint chk_flid_regex 
    check(ActorId like'[A-Z][a-z][A-Z]' collate sql_latin1_general_CP1_CS_AS)
);

例如。如果我给这样的东西 '[A-Z][a-z][A-Z]' 服务器只检查第一个 [A-Z]。第三个 [A-Z] 未选中。

因此,如果我插入诸如“Abc”之类的值,则它实际上不应该插入到表中。然而,它没有给出任何错误。它应该只接受像“AbC”这样的字符。

【问题讨论】:

  • 这有点时髦。我原以为区分大小写的排序规则会使它起作用。您也可以这样做的另一种方法是对您关心的三个字符建立一个检查语句,并确保它们分别在允许的字符范围内。类似 ascii(substring(actorId, 1, 1)) 的东西在 97 到 122 之间

标签: sql-server tsql case-sensitive sql-like check-constraints


【解决方案1】:

虽然我无法解释为什么 CS 排序规则不起作用,但切换到二进制排序规则的行为似乎符合您的预期,至少在 Sql Server 2008 中:

create table tbl
(
     FlowerId varchar(7)
constraint chk_flid_regex 
check(FlowerId like'[A-Z][a-z][A-Z]' collate Latin1_General_BIN)
);

Sql Fiddle

【讨论】:

  • 是的,使用二进制排序规则(_BIN_BIN2)是解决此问题的方法。原因与字典排序的概念有关,而不是在过滤范围时严格相等。我在这个答案中提供了详尽的解释:stackoverflow.com/questions/26176370/…+1。请参阅我在 Damien 的回答中留下的示例。
【解决方案2】:

你不能使用范围形式,你必须展开所有你想使用的字母:

create table
(
    FlowerId varchar(7)

    constraint chk_flid_regex 
    check(ActorId like'[ABCDEFGHIJKLMNOPQRSTUVWXYZ][abcdefghijklmnopqrstuvwxyz][ABCDEFGHIJKLMNOPQRSTUVWXYZ]' collate sql_latin1_general_CP1_CS_AS)
);

或者切换到二进制排序规则。为什么?因为在大多数排序规则中,小写字母放在大写字母之间,在大写字母之前或之后。因此A-Z 的范围扩展为AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZ - 您作为字母排除的所有内容都是小写z


(我希望每次在上面输入时我的字母都正确,但您可能需要仔细检查我没有遗漏任何字母)

【讨论】:

  • 嗯,是的,也不是;-)。您使用的 SQL Server 排序规则实际上首先对大写进行排序。但是,“Latin1_General_CS_AS”的 windows 排序规则首先对小写进行排序。使用以下内容进行测试:SELECT 1 WHERE 'a' LIKE '[A-C]' COLLATE SQL_Latin1_General_CP1_CS_AS; SELECT 2 WHERE 'a' LIKE '[ABC]' COLLATE SQL_Latin1_General_CP1_CS_AS; SELECT 3 WHERE 'A' LIKE '[a-c]' COLLATE SQL_Latin1_General_CP1_CS_AS; SELECT 4 WHERE 'a' LIKE '[A-C]' COLLATE Latin1_General_CS_AS; SELECT 5 WHERE 'A' LIKE '[a-c]' COLLATE Latin1_General_CS_AS; 您应该只返回“1”和“5”。
  • 重新阅读@srutzky 的评论。我认为sql_latin1_general_CP1_CS_AS 应该是AaBb...YyZ。 (因为,正如他的测试所示,'a' 介于'A''C' 之间,所以它不能在'A' 之前。)虽然我们在它上面,你的字母很好,除了小写序列有一个额外的 zed。
  • @AndriyM - 干杯。令人惊奇的是,您可以将这些东西看几十或几百次,但仍然没有发现明显的东西。
【解决方案3】:
^[A-Z][a-z][A-Z]$

添加锚点以禁止部分匹配。

【讨论】:

  • 这个答案与问题完全无关。标题(直到我刚刚修复它)确实具有误导性,但阅读这个问题应该很清楚这不是关于 RegEx 而是关于不支持锚点的 SQL LIKE 运算符。虽然,即使这是一个关于正则表达式的问题,这个答案仍然是错误的,因为 O.P. 声明 Abc 是匹配的,这与部分匹配无关。 -1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多