CHECK约束不工作

问题描述:

首先,我创建了一个表像CHECK约束不工作

CREATE TABLE Customer (
    SD integer CHECK (SD > 0), 
    Last_Name varchar (30), 
    First_Name varchar(30) 
); 

,然后插入该表

INSERT INTO Customer values ('-2','abc','zz'); 

MySQL的值没有显示错误,它接受的价值观。

+0

部分同意。鉴于您试图使用它,可以假定您提出了两个问题。事实上,你接受的答案主要是解释为什么它不起作用。 – igorrs 2013-01-10 00:21:19

+1

您可以对此功能请求进行投票:http://bugs.mysql.com/bug.php?id = 3464,但在十年内未收到任何关注。 – 2015-03-12 16:35:13

+0

我想知道在这个问题上删除投票的原因。 – nhahtdh 2015-03-23 08:51:46

CHECK约束似乎并没有在MySQL中实现。

看到这个错误报告:https://bugs.mysql.com/bug.php?id=3464

+17

我不知道这个,这真的很烦人! – Ben 2011-12-11 18:37:29

+0

已在MariaDB中修复(请参阅此答案https://*.com/a/44333349)。 – 2018-02-02 10:46:54

MySQL Reference Manual说:

CHECK子句解析,但所有的存储引擎忽略。

尝试触发...

mysql> delimiter // 
mysql> CREATE TRIGGER trig_sd_check BEFORE INSERT ON Customer 
    -> FOR EACH ROW 
    -> BEGIN 
    -> IF NEW.SD<0 THEN 
    -> SET NEW.SD=0; 
    -> END IF; 
    -> END 
    -> // 
mysql> delimiter ; 

希望有所帮助。

+5

在这里,你会发现如何触发一个错误,而不是:http://*.com/a/7189396/1144966 – petermeissner 2013-08-28 09:56:05

+23

这是众多闪闪发光的原因之一,我将永远使用PostgreSQL而不是MySQL给出任何选择。 – Reinderien 2014-11-11 07:05:23

+1

我不知道如果在分析器遇到一个定义的CHECK约束的情况下,MySQL会在10分钟或15分钟的时间内发出警告。啊,这太直接了...... – gaborsch 2016-12-14 13:58:36

尝试set sql_mode = 'STRICT_TRANS_TABLES' OR SET sql_mode='STRICT_ALL_TABLES'

+2

实际上并没有帮助(MySQL 5.6)它可以防止输入错误类型的数据,但不会输入不符合“CHECK”约束条件的数据 – petermeissner 2013-08-28 09:42:31

CHECK限制由MySQL被忽略,因为在文档微乎其微评论解释说:CREATE TABLE

CHECK条款进行解析,而是由所有存储发动机忽略。

+81

......这是惊人的。 – usr 2013-01-09 22:31:57

+2

@thefiloe:在其他DBMS中正确执行“CHECK”约束,如果“CHECK”评估为“FALSE”,那么插入(或更新)没有完成并导致错误。 – 2013-01-09 22:43:23

+0

已在MariaDB中修复(请参阅此答案https://*.com/a/44333349)。 – 2018-02-02 10:47:28

不幸的是,MySQL不支持SQL检查约束。您可以在DDL查询中将它们定义为兼容性原因,但它们只是被忽略。

有一个简单的替代

您可以创建BEFORE INSERTBEFORE UPDATE触发其或者导致错误或字段设置为默认值时,数据的要求没有得到满足。

举例BEFORE INSERT MySQL后,工作5.5

DELIMITER $$ 
CREATE TRIGGER `test_before_insert` BEFORE INSERT ON `Test` 
FOR EACH ROW 
BEGIN 
    IF CHAR_LENGTH(NEW.ID) < 4 THEN 
     SIGNAL SQLSTATE '12345' 
      SET MESSAGE_TEXT := 'check constraint on Test.ID failed'; 
    END IF; 
END$$ 
DELIMITER ; 

此前的MySQL 5.5,你不得不引起错误,例如调用一个未定义的过程。

在这两种情况下都会导致隐式事务回滚。 MySQL在过程和触发器中不允许ROLLBACK语句本身。

如果您不想回滚事务(即使失败的“检查约束”,INSERT/UPDATE也应该通过),您可以使用SET NEW.ID = NULL来覆盖该值,这会将id设置为字段的默认值,并不是真的对于身份证有意义

编辑: 删除了流浪的报价。

关于:=操作:

不像=,该:=运营商从未解释为比较操作。这意味着您可以在任何有效的SQL语句中使用:=(不仅仅在SET语句中)为变量赋值。

https://dev.mysql.com/doc/refman/5.6/en/assignment-operators.html

关于反引号标识符报价:

的标识符引号字符是反引号(“`”)

如果启用了ANSI_QUOTES SQL模式,也允许引用双引号内的标识符

http://dev.mysql.com/doc/refman/5.6/en/identifiers.html

+6

...不是非常简单,至少与CHECK :(比较:http://net.tutsplus.com/tutorials/databases/introduction-to-mysql-triggers/,http://www.sitepoint。com/how-to-create-mysql-triggers/ – Ben 2013-05-24 06:15:17

+0

呃,这看起来很庞大。我想我宁愿在python中创建一个元组,并在那里检查值,而不是将其放入。 – OzzyTheGiant 2017-01-05 15:32:54

+0

快速问题:为什么在未设置“DELIMITER”的情况下这不起作用? – ddz 2017-05-04 02:03:56

正如joanq提到MariaDB的,现在似乎支持其他物品中CHECK约束: “支持CHECK约束(MDEV-7563)”

https://mariadb.com/kb/en/mariadb/mariadb-1021-release-notes/