SQL 使用 UNIQUE 和 CHECK 的约束
SQL constraint with UNIQUE and CHECK
我的目标是在 "address" 与 "is_principal" 相同的 "account_id" 为真时阻止 INSERT(我只希望一个帐户有一个 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 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 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);
使用逗号分隔语法:
ALTER TABLE address ADD CONSTRAINT fk_account_adresses2_idx UNIQUE(account_id),
ADD CHECK (is_principal >= 1);
作为旁注,MySQL 8+ 之前的版本中的检查约束将被忽略。因此,如果您使用的是 MySQL 的早期版本,那么检查约束将被忽略。
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);
生成的列为具有 is_principal = TRUE
的记录生成 account_id
值,在另一种情况下为 NULL
。在 UNIQUE 约束中不检查 NULL。
虚拟生成的列不需要额外的磁盘space。
适用于 MySQL 从版本 5.7.8 开始(如果您不指定 VIRTUAL 并使用静态、存储的列,则从 5.7.6 开始)。
我的目标是在 "address" 与 "is_principal" 相同的 "account_id" 为真时阻止 INSERT(我只希望一个帐户有一个 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 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 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);
使用逗号分隔语法:
ALTER TABLE address ADD CONSTRAINT fk_account_adresses2_idx UNIQUE(account_id),
ADD CHECK (is_principal >= 1);
作为旁注,MySQL 8+ 之前的版本中的检查约束将被忽略。因此,如果您使用的是 MySQL 的早期版本,那么检查约束将被忽略。
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);
生成的列为具有 is_principal = TRUE
的记录生成 account_id
值,在另一种情况下为 NULL
。在 UNIQUE 约束中不检查 NULL。
虚拟生成的列不需要额外的磁盘space。
适用于 MySQL 从版本 5.7.8 开始(如果您不指定 VIRTUAL 并使用静态、存储的列,则从 5.7.6 开始)。