mysql - 执行具有完整性约束的 'subset' 关系的最佳方法是什么

标签 mysql sql-server oracle database-design postgresql

例如,给定 3 个表:

  • 腹足动物
  • 蜗牛
  • 鼻涕虫

假设我们想要强制执行

  1. “腹足动物”中的每一行在“蜗牛”或“蛞蝓”(但不是两者)中都有对应的一行
  2. “slug”中的每一行在“gastropod”中恰好对应一行
  3. “snail”中的每一行在“gastropod”中恰好对应一行

设置架构以强制执行这些约束的最佳方式是什么?

我已经为 postgres 提供了一个可能的答案,我对 postgres 和 Oracle 的解决方案特别感兴趣,但也有兴趣查看其他 RDBMS 的解决方案

编辑
作为引用,来自以下解决类似问题的答案/评论中的问题:

最佳答案

我自己的 postgres 解决方案(但我不知道这是否是最好的方法):

枚举:

create type gastropod_type as enum ('slug', 'snail');

表和约束:

create table gastropod(
  gastropod_id serial unique,
  gastropod_type gastropod_type,
  slug_gastropod_id integer,
  snail_gastropod_id integer,
  average_length numeric,
  primary key(gastropod_id, gastropod_type),
  check( (case when slug_gastropod_id is null then 0 else 1 end)+
         (case when snail_gastropod_id is null then 0 else 1 end)=1) );

create table slug(
  gastropod_id integer unique,
  gastropod_type gastropod_type check (gastropod_type='slug'),
  is_mantle_visible boolean,
  primary key(gastropod_id, gastropod_type),
  foreign key(gastropod_id, gastropod_type) 
    references gastropod deferrable initially deferred );

create table snail(
  gastropod_id integer unique,
  gastropod_type gastropod_type check (gastropod_type='snail'),
  average_shell_volume numeric,
  primary key(gastropod_id, gastropod_type),
  foreign key(gastropod_id, gastropod_type)
    references gastropod deferrable initially deferred );

alter table gastropod 
add foreign key(slug_gastropod_id, gastropod_type) 
references slug deferrable initially deferred;

alter table gastropod 
add foreign key(snail_gastropod_id, gastropod_type) 
references snail deferrable initially deferred;

测试:

insert into gastropod(gastropod_type, slug_gastropod_id, average_length)
values ('slug', currval('gastropod_gastropod_id_seq'), 100);

insert into slug(gastropod_id, gastropod_type, is_mantle_visible)
values (currval('gastropod_gastropod_id_seq'), 'slug', true);

select gastropod_id, gastropod_type, average_length, is_mantle_visible
from gastropod left outer join slug using(gastropod_id, gastropod_type) 
               left outer join snail using(gastropod_id, gastropod_type);

 gastropod_id | gastropod_type | average_length | is_mantle_visible
--------------+----------------+----------------+-------------------
            1 | slug           |            100 | t                 
(1 row)

关于mysql - 执行具有完整性约束的 'subset' 关系的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5522320/

相关文章:

mysql - 自动生成代理项对要插入的许多行显示错误

Java SQL 结果集数据类型

oracle - oracle中的多列索引是如何工作的?

javascript - 如何使用 sequelize model.findAll() 获取表的最大值

mysql - SQL - 按另一个具有多行的 SQL 语句分组

php - 如何在mysql数据库中存储拼音

c# - 如何将 Oracle 异常消息与字符串进行比较?

mysql - 这个查询似乎还没有完成。怎么了?

sql - Unicode - VARCHAR 和 NVARCHAR

sql - 服务代理队列正在禁用自身,无法找出原因