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中似乎没有实现检查约束 请参阅此错误报告:是第一个支持检查约束的版本 阅读 如果您使用MyS

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

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 ;
mysql>分隔符//
mysql>在插入客户之前创建触发器触发器sd检查
->每行
->开始
->如果NEW.SD设置为NEW.SD=0;
->如果结束;
->结束
-> //
mysql>分隔符;

希望能有所帮助。

尝试使用
设置sql\u模式='STRICT\u TRANS\u TABLES'
设置sql\u模式='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 ;  
分隔符$$
在插入之前创建触发器“test\u before\u insert`before insert ON`test”`
每行
开始
如果字符长度(NEW.ID)<4,则
信号状态“12345”
设置消息_TEXT:=“检查Test.ID上的约束失败”;
如果结束;
完$$
定界符;
在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允许表的核心特性 和列检查约束,用于所有存储引擎。创建表 对于这两个表,允许使用以下检查约束语法 约束和列约束


@thefiloe:Correct,在其他数据库管理系统中,使用正确的
CHECK
约束,如果
CHECK
计算结果为
FALSE
,则插入(或更新)未完成,并导致错误。在MariaDB中修复(参见此答案)。@Jérôme我知道,我有一些(最近的)答案包括在这方面的改进(在MariaDB正确实现检查约束之前,MariaDB和MySQL中都有其他解决此问题的方法)。我不确定的是我是否应该去编辑我所有的旧答案!我想我的评论加上一个最近答案的链接是可以的。或者总比什么都没有好。也许我应该编辑。我不是想给你施加压力让你做任何事。部分同意。考虑到你试图使用它,可以假设你在问这两个问题。事实上,您接受的答案主要是解释为什么它不起作用。您可以对这个功能请求进行投票:但它在十年内没有受到任何关注。您可以在MariaDB中使用检查约束。现在MySQL 8.0.16终于解决了这个问题,是时候无声地承认(!)忽略的内联引用规范了(另一大SQL标准不兼容):……不太简单,至少与CHECK相比:(.Coupla tutes:,呃,这看起来很笨重。我想我宁愿在python中创建一个元组,并在其中检查值,而不是将其放入。快速问题:如果不设置
分隔符,为什么这不起作用?但为什么?我的意思是,他们可以删除该命令。保留该命令并删除其功能有什么意义ty?该命令是在Mysql遵循的SQL的ANSI标准中定义的。这实际上没有帮助(Mysql 5.6)它可以防止输入错误类型的数据,但不能防止输入不符合
检查
约束条件的数据。在这里,您将发现如何触发错误:这是我始终使用PostgreSQL而不是MySQL的众多原因中的一个。我想知道这是10分钟还是15分钟的开发时间在MySQL中选择抛出