【问题标题】:SQL Check constraint on substrings对子字符串的 SQL 检查约束
【发布时间】:2012-04-24 13:28:21
【问题描述】:

请原谅我,如果这个问题在 SO 上的另一张票中得到解决...我一直在寻找,但似乎找不到完全正确的解决方案...

我正在创建一个表。 “Creditor”列一直是数字,除了最后一个字符可能是破折号。

这意味着像“1234-”、“92846293”等示例是有效的,而“12354-53”、“12345K”是无效的。 字符串长度不固定(除了它是一个 varchar(50))。

我不知道如何创建检查约束。

请帮忙!

【问题讨论】:

  • 这通常不是你可以用检查约束做的事情......当然不是在 ANSI SQL 中。您正在使用什么平台?

标签: sql substring check-constraints


【解决方案1】:

您没有说明您的 DBMS。对于 PostgreSQL,这将是:

alter table foo 
  add constraint check_creditor check (creditor ~ '^([0-9]+)\-?$');

对于 Oracle,这将是:

alter table foo 
   add constraint check_creditor check (regexp_like(creditor, '^([0-9]+)\-?$'))

如果您的 DBMS 支持正则表达式,您将需要使用 DBMS 的语法来检查这一点。不过,正则表达式本身 '^([0-9]+)\-$' 很可能是相同的。

【讨论】:

  • 我不是正则表达式专家,但看到最后一个字符是可选的,不应该是:^([0-9]+)-?$
【解决方案2】:

感谢您的回复。

'%[^0-9]%' 的提议让我大开眼界,因为我以前不知道 ^ 运算符。

我做了两个版本的所需约束。一种使用“仅”AND、OR、子字符串和非数字。没有花哨的索引或排除。太长了。 另一个版本由 AND、OR、子字符串和 insmuric 组成,但包含了建议的 ^ 操作。看起来好多了。

然后,最后,我采用了第三种解决方案 :-) 在数据库中添加了一个布尔列 RequiresCreditorValidation,并在我的 C# 代码中实现了一个正则表达式。

对于希望从结果检查中受益的其他人,他们在这里。 从“丑”开始:

CHECK ((val NOT IN ('+','-') AND (ISNUMERIC(val) = 1) OR 
(ISNUMERIC(SUBSTRING(val, 1, DATALENGTH(val) -1))) = 1) AND 
((SUBSTRING(val, (DATALENGTH(val)),1) LIKE '[0-9]') OR 
(SUBSTRING(val, DATALENGTH(val),1) = '-')) AND 
(SUBSTRING(val, 1, 1) NOT IN ('+','-')) )

第二个:

CHECK ( (SUBSTRING(val, 1, DATALENGTH(val) - 1) NOT LIKE '%[^0-9]%') AND 
(SUBSTRING(val, DATALENGTH(val),1) LIKE '%[0-9-]') AND (DATALENGTH(val) > 0) 
AND SUBSTRING(val, 1,1) NOT IN ('+','-') )

然后是正则表达式:

var allButLast = kreditorId.Substring(0, kreditorId.Length - 1);
        if (Regex.Match(allButLast, "[^0-9]").Success)
            return false;
        if (!kreditorId.EndsWith("-"))
            if (Regex.Match(kreditorId, "[^0-9]").Success)
                return false;
        return true;

感谢大家的优质、合格和快速的回​​复。

【讨论】:

    【解决方案3】:

    对于 SQL Server:

    测试 1:除最后一个之外的所有字符都是数字(或者,不存在非数字字符):

    CHECK ( SUBSTRING(Creditor, 1, LEN(Creditor) - 1) NOT LIKE '%[^0-9]%' )
    

    测试 2:最后一个字符是数字或破折号:

    CHECK ( SUBSTRING(Creditor, LEN(Creditor), 1) LIKE '%[0-9-%]' )
    

    以上假设Creditor不能是空字符串,即

    CHECK ( LEN(Creditor) > 0 )
    

    只是为了好玩:

    CHECK ( REVERSE(CAST(REVERSE(Creditor) + REPLICATE(0, 50) AS CHAR(50))) 
               LIKE REPLICATE('[0-9]', 49) + '[0-9-]' )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      • 2020-05-09
      • 2021-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多