数据库中是否可接受循环引用?

yli*_*yli 26 database oracle circular-dependency

数据库中何时可接受循环引用?

理论和实践,任何帮助表示赞赏.

fis*_*est 26

考虑城市和州.每个城市都在一个州内.每个州都有一个首都.

CREATE TABLE city (
  city  VARCHAR(32),
  state VARCHAR(32) NOT NULL,
  PRIMARY KEY (city),
  FOREIGN KEY (state) REFERENCES state (state)
);

CREATE TABLE state (
  state VARCHAR(32),
  capital_city VARCHAR(32),
  PRIMARY KEY (state),
  FOREIGN KEY (capital_city) REFERENCES city (city)
);
Run Code Online (Sandbox Code Playgroud)

第一个问题 - 您无法如图所示创建这些表.解决方案是在没有外键的情况下创建它们,然后添加外键.

第二个问题 - 您无法在任何表中插入行,因为每个插入都需要在另一个表中预先存在的行.解决方案是将其中一个外键列设置为NULL,并将该数据分两个阶段插入.例如

--Create state record
INSERT INTO state (state, capital_city) VALUES ('Florida', NULL);

--Create various city records
INSERT INTO city (city, state) VALUES ('Miami', 'Florida');
INSERT INTO city (city, state) VALUES ('Tallahassee', 'Florida');
INSERT INTO city (city, state) VALUES ('Orlando', 'Florida');

--Set one of the cities as the capital
UPDATE state SET capital_city = 'Tallahassee' WHERE state = 'Florida';
Run Code Online (Sandbox Code Playgroud)

  • 某些数据库(例如 postgresql)允许您将约束检查推迟到事务结束,使用诸如 SET CONSTRAINTS foo, bar DEFERRED 之类的命令 (2认同)

Mr.*_* 安宇 14

指向其他记录的记录在数据库中很有用.有时这些记录形成一个循环.这可能仍然有用.实践中唯一真正的烦恼是避免违反限制.

例如,如果您有用户和事务表,则该用户可能具有指向其上一个事务的指针.您需要先插入事务,然后将其更新last_transaction_id为正确的值.虽然这两个记录都存在,但你无法删除它们,因为user.last_transaction_id要点transaction.idtransaction.user_id指向user.id.这意味着没有事务的用户具有null last_transaction_id.这也意味着您必须先删除该字段,然后才能删除该事务.

管理这些外键约束是一种痛苦,但它肯定是可能的.如果稍后向数据库添加约束会引入新的循环依赖关系,则可能会出现问题.在这种情况下你必须要小心.但是,只要循环中的一个记录具有可空的外键字段,就可以中断循环并删除记录.只要您按正确的顺序插入记录,更新通常不是问题.


Con*_*lls 5

这在技术上是可行的,但在删除记录时可能会导致各种问题,因为它会产生先有鸡还是先有蛋的问题。这些问题通常需要采取激烈的措施来解决,例如手动删除 FK 并删除有问题的项目。

如果你们有这样的关系:

create table foo_master (
       foo_master_id int not null primary key
      ,current_foo_id int
)


create table foo_detail (
       foo_detail_id int not null primary key
       foo_master_id int not null
)

alter table foo_master
  add constraint fk_foo_current_detail
      foreign key (current_foo_id)
      references foo_detail

alter table foo_detail
  add constraint fk_foo_master
      foreign key (foo_master_id)
      references foo_master
Run Code Online (Sandbox Code Playgroud)

然后,由于循环依赖,删除一条记录可能会导致这样的鸡和聚合问题。

更好的架构如下所示:

create table foo_master (
       foo_master_id int not null primary key
)


create table foo_detail (
       foo_detail_id int not null primary key
       foo_master_id int not null
       is_current char (1)
)

alter table foo_detail
  add constraint fk_foo_master
      foreign key (foo_master_id)
      references foo_master
Run Code Online (Sandbox Code Playgroud)

这意味着该关系是非循环的,并且仍然可以识别“当前”foo_detail 记录。


Jef*_*emp 5

Oracle 分层查询语法的最新添加之一 -NOCYCLE关键字 - 专门用于此目的 - 处理数据中的循环引用。我没有发现它有什么问题,并且之前不得不处理这种模型。这并不太难,尤其是在支持延迟约束的 Oracle 中。