外键引用目标不存在

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了外键引用目标不存在相关的知识,希望对你有一定的参考价值。

我需要同步来自不同Firebird数据库的两个表中的数据。确切地说,我需要使用表Users(2nd DB)中的记录更新表Person(1st DB)中的记录。不仅是“名字”,“电子邮件”,“生日”,而且ID也是(!)。问题是 - 有表,通过FOREIGN KEY约束依赖于Person的ID。

我正在尝试这样做:

  1. 删除依赖表中的外键约束。
  2. 同步两个表(这意味着更新/更改表Person中的ID)
  3. 在依赖表中更改适当的ID。
  4. 在依赖表中添加外键约束。

最后一步导致错误(从java应用程序登录,但如果我直接在IBExpert中执行这些步骤则相同):

com.bssys.db.jdbc.DBSQLException: GDS Exception. 335544466. violation of FOREIGN KEY constraint "FK_EMPLOYEE_PERSON" on table "EMPLOYEE"
Foreign key reference target does not exist, error code: HY000
Reason: violation of FOREIGN KEY constraint "FK_EMPLOYEE_PERSON" on table "EMPLOYEE"

(员工 - 是依赖表之一)

我的问题是,我能否避免这个错误。或者也许有一些关于如何更改相关表中的ID的想法。可能有特殊的RDBMS工具来同步数据库,但我需要通过Java应用程序同步它们,因此只使用sql和java。我使用Firebird 2.5.1。

完整的SQL语句(示例):

  1. ALTER TABLE employee DROP CONSTRAINT fk_employee_person
  2. UPDATE person SET id = 555555 WHERE id = 3000005
  3. UPDATE employee SET person_id = 555555 WHERE person_id = 3000005
  4. ALTER TABLE employee ADD CONSTRAINT fk_employee_person FOREIGN KEY (person_id) REFERENCES person(id)

一些新信息:似乎有时IBExpert允许我完成这些步骤。实际上,如果我在其中一个表处于“DATA”模式时更改了所有ID,则会出现错误(我想,它也是某种交易,如CREATE VIEW)。

我还发现删除/添加外键需要对整个数据库进行独占锁定,至少要等到Firebird 2.1(甚至2.5)

答案

您应该创建表,以便外键具有ON UPDATE CASCADE子句 - 然后当您更新ID时,它也会在从属表中更新,而您无需任何额外的工作。因此,对于每个引用Person表的表,您需要执行以下操作:

-- delete the original FK constraint
ALTER TABLE _table_ DROP CONSTRAINT _fk_constraint_name_;
-- (re)add the FK constraint with ON UPDATE CASCADE
ALTER TABLE _table_ ADD CONSTRAINT _fk_constraint_name_ FOREIGN KEY (person_id) REFERENCES person(id) ON UPDATE CASCADE;
另一答案

不使用主键重新编号,而是使用正确的主键将新记录插入person,然后更新employee的外键值并删除旧的person记录。

注意:下面的部分是主观的,更多的是意见而不是事实。

顺便说一句:重新编号主键的需要通常表明存在设计问题。主键在数据库之外应该没有意义,它们通常应该在给定记录的生命周期内保持稳定。在你的情况下,键显然也意味着数据库之外的东西,也是不稳定的。

如ain的答案所示,你可以使用ON UPDATE CASCADE,但恕我直言,这通常是问题的补丁,而不是解决方案。解决方案是:如果您有不稳定的主键:创建这些唯一键并添加无意义的主键,不需要更改。

以上是关于外键引用目标不存在的主要内容,如果未能解决你的问题,请参考以下文章

外键的引用说表不存在

添加列作为外键会给出外键约束中引用的 ERROR 列不存在

外键对数据插入的影响

外键对数据更新的影响

Restkit:当外键引用Core Data中缺少的本地对象时获取远程链接对象

外键和引用类如何在 Hibernate 实体中一起存在?