如何检查 MySQL 中约束中外键引用的记录的值
How to check a value of a record referenced by foreign key in a constraint in MySQL
我目前在 arch 上使用 MariaDB,在 "production".
中,debian buster 代表 mysql
我正在尝试创建以下架构:
create or replace schema `test`
use `test`;
create table `tags`
(
`tag_id` int not null auto_increment,
`tag_display_name` varchar(200) not null unique,
`tag_meta` boolean not null,
primary key (`tag_id`)
);
create table `tag_aliases`
(
`alias_id` int not null,
`tag_id` int not null,
primary key (`alias_id`, `tag_id`),
foreign key (`alias_id`) references `tags` (`tag_id`),
foreign key (`tag_id`) references `tags` (`tag_id`),
-- This constraint I am trying to make that doesn't work (some kind of syntax error 1064)
CONSTRAINT `cnstrnt` check (select `tag_meta` from `tags` where `tag_id`=`alias_id` limit 1)
);
目标是与 tags
建立 m:n 关系,其中 tag_meta
列为真,并且与任何其他 tags
(元或非元)。
但是我找不到任何相关资源,因为每次我尝试 google 我都看到外键约束无处不在。
我也试过做一个函数,但是它说这个函数不能用在检查子句中。 (错误 1901)
-- The function
DELIMITER //
create or replace function tagIsMeta(id int) returns boolean
begin
declare res boolean default null;
select `tag_meta` into res from `tags` where `tag_id` = id limit 1;
return res;
end //
DELIMITER ;
-- The constraint
create table ....
(
...
...
CONSTRAINT `cnstrnt` check (tagIsMeta(`alias_id`))
);
这是一个解决方案:
create table `tags` (
`tag_id` int not null auto_increment,
`tag_display_name` varchar(200) not null unique,
`tag_meta` boolean not null,
primary key (`tag_id`),
key (`tag_id`, `tag_meta`)
);
create table `tag_aliases` (
`alias_id` int not null,
`tag_id` int not null,
`tag_meta` boolean not null default true,
primary key (`alias_id`),
foreign key (`alias_id`) references `tags` (`tag_id`),
foreign key (`tag_id`, `tag_meta`) references `tags` (`tag_id`, `tag_meta`),
check (`tag_meta` = true)
);
这使用了 InnoDB 的非标准功能,它允许外键引用父项的非唯一索引 table。通常这是要避免的事情,因为子行引用 multiple 父行意味着什么?但在这种情况下,由于 tags.tag_id
本身是唯一的,所以不会发生这种情况。
其工作方式是 tag_aliases
中的列对必须与 tags
中的对应列匹配。但是我们在 tag_aliases.tag_meta
上设置了一个检查约束,它必须是 true,因此只有当它引用 tags
中具有 tag_meta = true
.
我目前在 arch 上使用 MariaDB,在 "production".
中,debian buster 代表 mysql我正在尝试创建以下架构:
create or replace schema `test`
use `test`;
create table `tags`
(
`tag_id` int not null auto_increment,
`tag_display_name` varchar(200) not null unique,
`tag_meta` boolean not null,
primary key (`tag_id`)
);
create table `tag_aliases`
(
`alias_id` int not null,
`tag_id` int not null,
primary key (`alias_id`, `tag_id`),
foreign key (`alias_id`) references `tags` (`tag_id`),
foreign key (`tag_id`) references `tags` (`tag_id`),
-- This constraint I am trying to make that doesn't work (some kind of syntax error 1064)
CONSTRAINT `cnstrnt` check (select `tag_meta` from `tags` where `tag_id`=`alias_id` limit 1)
);
目标是与 tags
建立 m:n 关系,其中 tag_meta
列为真,并且与任何其他 tags
(元或非元)。
但是我找不到任何相关资源,因为每次我尝试 google 我都看到外键约束无处不在。
我也试过做一个函数,但是它说这个函数不能用在检查子句中。 (错误 1901)
-- The function
DELIMITER //
create or replace function tagIsMeta(id int) returns boolean
begin
declare res boolean default null;
select `tag_meta` into res from `tags` where `tag_id` = id limit 1;
return res;
end //
DELIMITER ;
-- The constraint
create table ....
(
...
...
CONSTRAINT `cnstrnt` check (tagIsMeta(`alias_id`))
);
这是一个解决方案:
create table `tags` (
`tag_id` int not null auto_increment,
`tag_display_name` varchar(200) not null unique,
`tag_meta` boolean not null,
primary key (`tag_id`),
key (`tag_id`, `tag_meta`)
);
create table `tag_aliases` (
`alias_id` int not null,
`tag_id` int not null,
`tag_meta` boolean not null default true,
primary key (`alias_id`),
foreign key (`alias_id`) references `tags` (`tag_id`),
foreign key (`tag_id`, `tag_meta`) references `tags` (`tag_id`, `tag_meta`),
check (`tag_meta` = true)
);
这使用了 InnoDB 的非标准功能,它允许外键引用父项的非唯一索引 table。通常这是要避免的事情,因为子行引用 multiple 父行意味着什么?但在这种情况下,由于 tags.tag_id
本身是唯一的,所以不会发生这种情况。
其工作方式是 tag_aliases
中的列对必须与 tags
中的对应列匹配。但是我们在 tag_aliases.tag_meta
上设置了一个检查约束,它必须是 true,因此只有当它引用 tags
中具有 tag_meta = true
.