MySQL 5.5继承关系模型中的完整性约束问题

发布于 2024-12-04 15:43:27 字数 720 浏览 6 评论 0原文

我有以下数据库关系模式,旨在对 EMP 超类型以及两个 FULL_TIME_EMP 和 PART_TIME_EMP 子类型进行建模:

database schema 我遇到的问题是完整性问题,即我想确保全职员工只能在 FULL_TIME_EMP 表中拥有相应的行,同样,兼职员工只能在 PART_TIME_EMP 表中拥有相应的行。

正如您将从下面的屏幕截图中看到的那样,不强制执行此完整性约束。

这是 EMP_TYPE 表: EMP_TYPE table

和 EMP 表: EMP 表

PART_TIME_EMP 表: PART_TIME_EMP table

最后是 FULL_TIME_EMP 表,它显示了完整性违规FULL_TIME_EMP table

有没有办法通过改变我的数据库模型设计来强制执行此完整性约束,或者我是否必须诉诸触发器?

问候,

I have the following database relational schema that purports to model an EMP supertype together with two FULL_TIME_EMP and PART_TIME_EMP subtypes:

database schema
The problem I have is one of integrity i.e. I would like to make sure that a full-time employee can only have a corresponding row in the FULL_TIME_EMP table and similarly a part-time employee can only have a correponding row in the PART_TIME_EMP table.

As you will see from the screen captures below, this integrity constraint is not enforced.

Here is the EMP_TYPE table:
EMP_TYPE table

And the EMP table:
EMP table

The PART_TIME_EMP table:
PART_TIME_EMP table

And finally the FULL_TIME_EMP table which presents the integrity violation!!
FULL_TIME_EMP table

Is there a way to enforce this integrity constraint by altering my database model design or do I have to resort to triggers?

Regards,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心的憧憬 2024-12-11 15:43:27

您不必求助于触发器,但它可能会有所帮助。改变结构会有很大帮助,但它通常依赖于 CHECK 约束。在MySQL中,如果需要CHECK约束,则必须编写触发器或添加另一个使用外键约束的表。

您还有额外的负担,因为兼职员工后来可能成为全职员工,反之亦然。

下面是我如何为更标准的 SQL 平台编写它。

create table emp (
  emp_id integer primary key,
  emp_type char(1) not null check (emp_type in ('f', 'p')), -- FK in your schema
  emp_name varchar(50) not null,
  start_date date not null default current_date,
  unique (emp_id, emp_type)
);

create table full_time_emp (
  emp_id integer primary key references emp (emp_id),
  emp_type char(1) not null default 'f' check (emp_type = 'f'),
  foreign key (emp_id, emp_type) references emp (emp_id, emp_type),
  salary decimal(14,2) not null check (salary > 15000)
);

create table part_time_emp (
  emp_id integer primary key references emp (emp_id),
  emp_type char(1) not null default 'p' check (emp_type = 'p'),
  foreign key (emp_id, emp_type) references emp (emp_id, emp_type),
  rate decimal(14,2) not null check (rate > 0 and rate < 100)
);

在表 full_time_emp 中,这两个约束

  check (emp_type = 'f'),
  foreign key (emp_id, emp_type) references emp (emp_id, emp_type),

一起防止兼职员工出现在全职表中。如果“emp”中引用的行包含“p”,则外键引用将失败;如果您尝试将“p”插入“full_time_emp”,检查约束将失败。

在这种情况下,您可以用单行表和外键引用替换检查约束。该表应仅包含“f”。 (或者您用来代表全职员工的任何 ID 号。)同样的事情也适用于“part_time_emp”。因此,您可以对 full_time_emp 执行此操作,而不是 CHECK 约束。

create table full_time_emp_check (
  full_time_emp_type char(1) primary key
);
insert into full_time_emp_check values ('f');

alter table full_time_emp
add constraint full_time_emp_check
foreign key (emp_type) references full_time_emp_check (full_time_emp_type);

part_time_emp 的更改类似。您可能需要在这两个表上都有一个触发器,以确保它们永远不会包含多于一行。

甚至对工资和费率的检查也可以通过附加表格和外键引用来实现。不过,这有点像把死去的鲸鱼踢到海滩上。我可能会使用 MySQL 中的触发器来实现那种范围约束。

恕我直言,对于员工类型来说,CHAR(1) 代码比整数更好。人类可读的代码不需要联接。

You don't have to resort to triggers, but it might help. Changing the structure will help a lot, but it normally relies on CHECK constraints. In MySQL, if you need a CHECK constraint, you have to write a trigger or add another table that uses a foreign key constraint.

You have an additional burden, in that a part-time employee could later become full time, and vice versa.

Here how I'd write it for a more standard SQL platform.

create table emp (
  emp_id integer primary key,
  emp_type char(1) not null check (emp_type in ('f', 'p')), -- FK in your schema
  emp_name varchar(50) not null,
  start_date date not null default current_date,
  unique (emp_id, emp_type)
);

create table full_time_emp (
  emp_id integer primary key references emp (emp_id),
  emp_type char(1) not null default 'f' check (emp_type = 'f'),
  foreign key (emp_id, emp_type) references emp (emp_id, emp_type),
  salary decimal(14,2) not null check (salary > 15000)
);

create table part_time_emp (
  emp_id integer primary key references emp (emp_id),
  emp_type char(1) not null default 'p' check (emp_type = 'p'),
  foreign key (emp_id, emp_type) references emp (emp_id, emp_type),
  rate decimal(14,2) not null check (rate > 0 and rate < 100)
);

In the table full_time_emp, these two constraints

  check (emp_type = 'f'),
  foreign key (emp_id, emp_type) references emp (emp_id, emp_type),

taken together prevent part-time employees from appearing in the full-time table. If the referenced row in "emp" contains 'p', the foreign key reference will fail; if you try to insert a 'p' into "full_time_emp", the check constraint will fail.

In this case, you can replace the check constraint with a one-row table and a foreign key reference. The table should contain only 'f'. (Or whatever ID number you use to represent a full-time employee.) Same thing works for "part_time_emp". So instead of the CHECK constraint, you could do this for full_time_emp.

create table full_time_emp_check (
  full_time_emp_type char(1) primary key
);
insert into full_time_emp_check values ('f');

alter table full_time_emp
add constraint full_time_emp_check
foreign key (emp_type) references full_time_emp_check (full_time_emp_type);

Changes for part_time_emp are similar. You might want a trigger on both those tables to make sure they never contain more than one row.

Even the checks on salary and rate could be implemented with additional tables and foreign key references. Be kind of like kicking dead whales down the beach, though. I'd probably implement that kind of range constraint with a trigger in MySQL.

IMHO, a CHAR(1) code is better than an integer for employee types. A human-readable code doesn't require a join.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文