具有UNIQUE和CHECK的SQL约束

时间:2020-02-28 09:42:36

标签: mysql constraints unique ddl

我的目标是,如果“地址”与“ is_principal”具有相同的“ account_id”,则阻止插入(我只希望每个帐户一个is_principal地址)。

是否可以使用UNIQUE和CHECK创建SQL约束?

我尝试:

ALTER TABLE address ADD CONSTRAINT fk_account_adresses2_idx UNIQUE(account_id, CHECK (is_principal >= 1)); 

错误:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CHECK (is_principal >= 1))' at line 1 (SQL: ALTER TABLE address ADD CONSTRAINT fk_compte_adresses2_idx UNIQUE(account_id, CHECK (is_principal >= 1));)

谢谢。

编辑:

应该工作的INSERT示例:

insert into `address` (`address`, `account_id`, `is_principal`) values (address 1, 1, 1);
insert into `address` (`address`, `account_id`, `is_principal`) values (address 2, 1, 0);
insert into `address` (`address`, `account_id`, `is_principal`) values (address 3, 1, 0);

应该失败的INSERT示例:

insert into `address` (`address`, `account_id`, `is_principal`) values (address 1, 1, 1);
insert into `address` (`address`, `account_id`, `is_principal`) values (address 2, 1, 1);

2 个答案:

答案 0 :(得分:0)

使用逗号分隔的语法:

ALTER TABLE address ADD CONSTRAINT fk_account_adresses2_idx UNIQUE(account_id),
                    ADD CHECK (is_principal >= 1);

作为旁注,MySQL早于8+版本的检查约束将被忽略。因此,如果您使用的是MySQL的早期版本,则检查约束将被忽略。

答案 1 :(得分:0)

ALTER TABLE address 
ADD COLUMN for_check INT AS (CASE WHEN is_principal 
                                  THEN account_id 
                                  END) VIRTUAL,
ADD CONSTRAINT check_only_one_principal_address 
    UNIQUE INDEX (for_check);

fiddle

在另一种情况下,Generated列为具有account_idis_principal = TRUE的记录生成NULL值。在UNIQUE约束中不检查NULL。

虚拟生成的列不需要额外的磁盘空间。

从5.7.8版本开始适用于MySQL(如果您未指定VIRTUAL并使用静态的STORED列,则从5.7.6开始)。