0

假设数据库中有两个表。第一个是 X,第二个是 Y。Y 表在 X 表上有一个外键。因此,如果 Y 表上有记录,则它的外键相关列值必须存在于 X 表上。这是默认行为。

   X         Y
-------   -------
  ID        ID
            XID <--- Foreignkey to X table.

现在,对于 X 表中的所有记录,我想保证 Y 表上必须至少有一条记录。如果没有,它应该自动添加一个。我怎样才能做到这一点?

4

2 回答 2

1

要将丢失的记录插入Y现有数据,您可以运行类似

INSERT INTO Y(xid)
SELECT x.id 
FROM x 
WHERE NOT EXISTS(SELECT NULL FROM Y a WHERE a.xid = x.id);

为了以后防止这样的事情发生,写一个在2个表中插入数据的过程,防止大家直接往表中插入数据(只能通过这个过程)

于 2012-12-16T13:30:17.960 回答
1

这里有两个不同的问题。

  1. 管理声明性约束。
  2. 管理插入、更新和删除。

保证 x 中的每一行在 y 中都存在一行的“正常”方法是在两个表中都包含外键。每个表引用另一个。

create table x (
  x_id integer primary key,
  y_id integer not null
);

create table y (
  y_id integer primary key,
  x_id integer not null references x (x_id)
);

alter table x
add constraint one_to_one
foreign key (y_id)
  references y (y_id) deferrable initially deferred;

begin transaction;
insert into x values (1, 100);
insert into y values (100, 1);
commit;

虽然这保证了每个“x”都有一个“y”,但可以这么说,它并不能保证每个“x”都有一个不同的“y”,或者每个“x”都有自己的“y”。我不确定这是否是您的要求。

这不是您要寻找的因为您的两个表之间存在 1:N 关系。你可以让它工作,但我认为你必须编写一个触发器来管理对表“y”的更改。例如,如果用户从“y”中删除“x”持有外键引用的行,则需要更新“x”以引用“y”中的不同行。

但这会导致第二个问题:管理插入、更新和删除。有几种方法可以做到这一点。

  • 客户端负责提供保持数据库一致所需的所有语句。(除了上面的外键问题,最好在“y”的触发器中处理。)
  • 客户端无法直接访问基表。所有更改都是通过存储过程进行的。
  • 客户端无法直接访问基表。所有更改都通过可更新的视图进行。

存储过程和可更新视图可以让您在一定程度上自动在“y”中添加一行,但您必须编写程序代码才能做到这一点。

于 2012-12-16T14:57:33.037 回答