1

我需要同步来自不同 Firebird 数据库的两个表中的数据。准确地说,我需要使用表用户(第二个数据库)中的记录来更新表人(第一个数据库)中的记录。不仅是“姓名”、“电子邮件”、“生日”,还有 ID(!)。问题是 - 有些表通过外键约束依赖于人员的 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"

(Employee - 是从属表之一)

我的问题是,我是否可以避免这个错误。或者也许有一些关于如何更改相关表中的 ID 的想法。同步数据库可能有特殊的 RDBMS 工具,但我需要通过 Java 应用程序同步它们,因此只使用 sql 和 java。我使用火鸟 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)之前需要对整个数据库进行独占锁定

4

2 回答 2

3

您应该创建表,以便外键确实具有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;
于 2012-11-29T16:27:26.707 回答
1

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

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

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

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

于 2012-11-30T11:02:29.997 回答