Java 外键引用目标不存在

Java 外键引用目标不存在,java,synchronization,foreign-keys,constraints,firebird,Java,Synchronization,Foreign Keys,Constraints,Firebird,我需要同步来自不同Firebird数据库的两个表中的数据。确切地说,我需要使用来自表用户(第二个DB)的记录更新表Person(第1个DB)中的记录。不仅是“姓名”、“电子邮件”、“生日”,还有身份证(!)。问题是,有些表通过外键约束依赖于个人ID 我正在尝试这样做: 删除依赖表中的外键约束 同步两个表(这意味着更新/更改table Person中的ID) 在依赖表中更改相应的ID 在依赖表中添加外键约束 最后一步导致错误(来自java应用程序的日志,但如果我直接在IBExpert中执行这些步骤

我需要同步来自不同Firebird数据库的两个表中的数据。确切地说,我需要使用来自表用户(第二个DB)的记录更新表Person(第1个DB)中的记录。不仅是“姓名”、“电子邮件”、“生日”,还有身份证(!)。问题是,有些表通过外键约束依赖于个人ID

我正在尝试这样做:

  • 删除依赖表中的外键约束
  • 同步两个表(这意味着更新/更改table Person中的ID)
  • 在依赖表中更改相应的ID
  • 在依赖表中添加外键约束
  • 最后一步导致错误(来自java应用程序的日志,但如果我直接在IBExpert中执行这些步骤,则相同):

    (Employee-是从属表之一)

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

    完整的SQL语句(示例):

  • 一些新信息:看起来有时候IBExpert允许我完成这些步骤。实际上,如果我在其中一个表处于“数据”模式时更改了所有ID,那么它会给出一个错误(我想这也是某种事务,比如
    创建视图


    我还发现,移除/添加外键需要对整个数据库进行独占锁定,至少在Firebird 2.1(甚至2.5)之前,您应该创建表,以便外键在更新级联时具有
    子句-然后在更新
    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;
    

    您应该创建表,以便外键在更新级联时具有
    子句,然后当您更新
    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的答案所示,您可以在更新级联上使用
    ,但这通常是问题的补丁,而不是解决方案。解决方法是:如果主键不稳定:创建那些唯一的键,并添加一个无意义的主键,而不需要更改。

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

    注:以下部分是主观的,更多的是观点而非事实

    顺便说一句:需要重新编号您的主键通常是一个设计问题的迹象。主键在数据库之外应该是无意义的,并且在给定记录的生命周期内它们通常应该保持稳定。显然,在您的情况下,密钥也意味着数据库之外的内容,并且不稳定


    正如ain的答案所示,您可以在更新级联上使用
    ,但这通常是问题的补丁,而不是解决方案。解决方案是:如果主键不稳定:生成那些唯一的键,并添加一个不需要更改的无意义主键。

    请向我们展示您正在执行的完整SQL语句在一个事务中执行步骤2和步骤3,或者你正在使用autocommit?请向我们展示你正在执行的完整SQL语句在一个事务中执行步骤2和步骤3,或者你正在使用autocommit?我个人喜欢“更新级联”,但我只是一个新手,正在处理一个已经很大的项目,由于某些原因没有使用这种结构。。实际上,我试图删除我的fk约束,添加带有“更新级联”选项的新约束,然后更新Person(id),然后再次删除fk约束,并在没有“更新级联”选项的情况下再次创建它们(我知道,这很蹩脚)。但它不起作用:/IBExpert在最后一步仍然给我一个错误。我个人很喜欢“更新级联”,但我只是一个新手,正在处理一个已经很大的项目,由于某些原因,这种结构没有被使用。。实际上,我试图删除我的fk约束,添加带有“更新级联”选项的新约束,然后更新Person(id),然后再次删除fk约束,并在没有“更新级联”选项的情况下再次创建它们(我知道,这很蹩脚)。但它不起作用:/IBExpert在最后一步仍然给我一个错误。韦尔多,谢谢你!我期待着实现您的解决方案^^对于设计有问题的DB应用程序来说,这是一个很好的解决方案。我稍后会写我的结果。至于ID同步,我也有一种感觉,这很奇怪,我问了老开发者,但他们说需要。谢谢!我期待着实现您的解决方案^^对于设计有问题的DB应用程序来说,这是一个很好的解决方案。我稍后会写我的结果。至于ID同步,我也有一种感觉,这很奇怪,我问了老开发者,但他们说这是必要的。
    UPDATE person SET id = 555555 WHERE id = 3000005
    
    UPDATE employee SET person_id = 555555 WHERE person_id = 3000005
    
    ALTER TABLE employee ADD CONSTRAINT fk_employee_person FOREIGN KEY (person_id) REFERENCES person(id)
    
    -- 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;