MySQL中的检查约束不起作用

MySQL中的检查约束不起作用,mysql,check-constraints,Mysql,Check Constraints,首先,我创建了一个表,如 CREATE TABLE Customer ( SD integer CHECK (SD > 0), Last_Name varchar (30), First_Name varchar(30) ); 然后在表中插入值 INSERT INTO Customer values ('-2','abc','zz'); MySQL没有显示错误,它接受了值。检查约束似乎没有在MySQL中实现 请参阅此错误报告:是第一个支持检查约束的版本 阅读 如果您使用My

首先,我创建了一个表,如

CREATE TABLE Customer (
  SD integer CHECK (SD > 0),
  Last_Name varchar (30),
  First_Name varchar(30)
);
然后在表中插入值

INSERT INTO Customer values ('-2','abc','zz');
MySQL没有显示错误,它接受了值。

检查约束似乎没有在MySQL中实现

请参阅此错误报告:

是第一个支持检查约束的版本

阅读

如果您使用MySQL 8.0.15或更早版本,则会显示:

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 ;
希望对您有所帮助。

尝试使用set-sql\u mode='STRICT\u TRANS\u TABLES'或set-sql\u mode='STRICT\u ALL\u TABLES'

检查MySQL忽略的约束,如文档中的一条小注释所述:

CHECK子句已解析,但被所有存储引擎忽略


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

有一个简单的选择

您可以创建“插入前”和“更新前”触发器,这会导致错误,或者在不满足数据要求时将字段设置为其默认值

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语句本身

如果您不想回滚事务插入/更新应该通过,即使检查约束失败,您也可以使用SET NEW.ID=NULL覆盖该值,这会将ID设置为字段默认值,对于ID tho来说没有意义

编辑: 删除了错误的引用

关于:=运算符:

与=,不同:=运算符从不被解释为比较运算符。这意味着您可以在任何有效的SQL语句中使用:=而不仅仅是在SET语句中,为变量赋值

关于反勾号标识符引号:

标识符引号字符是反勾“`”

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


正如joanq MariaDB所提到的,现在似乎在其他好处中支持检查约束:

支持检查约束


从尚未发布的版本8.0.15开始,支持检查约束

[23 Jan 16:24]Paul Dubois

开发者发布:在8.0.15中修复

之前,MySQL允许有限形式的检查约束语法, 但是解析并忽略了它。MySQL现在实现了 表和列检查约束,适用于所有存储引擎。 使用CREATETABLE和ALTERTABLE语句定义约束


更新到MySQL 8.0.16以使用检查:

从MySQL 8.0.16开始,CREATETABLE允许表的核心特性 和列检查约束,适用于所有存储引擎。创建表 对于这两个表,允许使用以下检查约束语法 约束和列约束



@FILOE:正确,在其他具有正确执行检查约束的DBMS中,如果检查结果为FALSE,则插入或更新未完成,并导致错误。已在MariaDB中修复。请参见此答案。@Jérôme我知道,我有一些最近的答案,包括在这方面的改进。在MariaDB正确实现检查约束之前,在MariaDB和MySQL中都有其他方法来解决这个问题。我不确定的是我是否应该去编辑我所有的旧答案!我想我的评论加上一个最近答案的链接是可以的。或者总比什么都没有好。也许我应该编辑一下。我不是想给你施加压力让你做任何事,我只是部分同意。考虑到您试图使用它,可以假设您同时提出了这两个问题。事实上,您接受的答案主要是解释为什么它不起作用。您可以对这个功能请求进行投票:但它已经十年没有受到任何关注了。您可以从开始在MariaDB中使用检查约束。现在MySQL 8.0.16终于解决了这个问题,是时候默默地承认了!忽略内联引用规范太多其他大的SQL标准不兼容:……不是很简单,至少与CHECK:。库普拉·图特斯:啊,这看起来很笨重。我想我宁愿在python中创建一个元组,并在其中检查值,而不是将其放入。快速问题:为什么不设置分隔符就不能工作?为什么?我是说,他们本可以取消命令的。保留该命令并删除其功能的目的是什么?该命令是在Mysql遵循的ANSI SQL标准中定义的。这实际上对MySQL 5.6没有帮助,因为它可以防止输入错误类型的数据,但不能防止输入不符合检查约束的数据。您将发现如何触发错误:这是我将始终使用Postgr的众多原因之一
eSQL而不是MySQL提供了一个选择。我想知道如果解析器遇到定义的检查约束,在MySQL中进行10分钟或15分钟的开发是否会引发警告。啊,那太直截了当了……在MariaDB中修复了,请看这个答案。