如果存在具有相同引用详细信息但不同名称的外键,则 foreignKeyConstraintExists 前提条件似乎不充分
foreignKeyConstraintExists Precondition Seems Not Adequate If Foreign Keys with Same Reference Details but Different Names Exist
当我使用 Liquibase 脚本升级现有数据库时(数据库从未被 Liquibase 升级),出现以下错误。
liquibase.exception.MigrationFailedException: Migration failed for change set ../master.xml::5::ray.chen:
Reason: liquibase.exception.DatabaseException: ORA-02275: such a referential constraint already exists in the table
[Failed SQL: ALTER TABLE CRDM_RCHEN.SOME_TABLE ADD CONSTRAINT SOME_TABLE_FK FOREIGN KEY (COLUMN_2) REFERENCES CRDM_RCHEN.SOME_OTHER_TABLE (COLUMN_1)]
at liquibase.changelog.ChangeSet.execute(ChangeSet.java:605)
at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:51)
at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:79)
at liquibase.Liquibase.update(Liquibase.java:214)
at liquibase.Liquibase.update(Liquibase.java:192)
at liquibase.integration.commandline.Main.doMigration(Main.java:1126)
at liquibase.integration.commandline.Main.run(Main.java:184)
at liquibase.integration.commandline.Main.main(Main.java:103)
我仔细检查了 Liquibase 脚本和数据库,数据库中已经存在名为 SOME_TABLE_1_FK 的外键。根本原因应该是 Liquibase 脚本将添加一个名为 SOME_TABLE_FK 的外键,但一个名为 SOME_TABLE_1_FK[=28 的外键=] 已经存在,具有相同的参考详细信息和不同的名称。似乎数据库不允许 2 个名称不同但引用详细信息相同的外键。
对于这个问题,您有什么解决方案或想法吗?谢谢
这是相关的 Liquibase 脚本。我使用foreignKeyConstraintExists前置条件检查外键SOME_TABLE_FK是否存在,如果不存在则添加;但是如果存在具有相同引用详细信息但不同名称的外键(上述情况),将执行变更集并发生上述错误。
<changeSet author="ray.chen" id="5">
<preConditions onFail="MARK_RAN">
<not>
<foreignKeyConstraintExists foreignKeyName="SOME_TABLE_FK" />
</not>
</preConditions>
<addForeignKeyConstraint constraintName="SOME_TABLE_FK" baseTableName="SOME_TABLE" baseColumnNames="COLUMN_2" referencedTableName="SOME_OTHER_TABLE" referencedColumnNames="COLUMN_1" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" />
</changeSet>
liquibase提供的foreignKeyConstraintExists
需要通过foreignKeyName
。为了检查是否有没有名称的外键,您需要编写自定义前提条件。下面是一个例子:
<preConditions onFail="MARK_RAN">
<not>
<customPrecondition className="com.ctp.liquibase.ForeignKeyExistsPrecondition">
<param name="schemaName" value="MYSCHEMA"/>
<param name="tableName" value="TABLE"/>
<param name="columnName" value="COLUMN"/>
<param name="foreignTableName" value="FTABLE"/>
</customPrecondition>
</not>
</preConditions>
以上将检查 table 上的列是否具有针对外部 table 的外键约束。
您可以找到更多 here。
为什么不只检查 both/all 个名字?
<preConditions onFail="MARK_RAN">
<not>
<foreignKeyConstraintExists foreignKeyTableName="SOME_TABLE" foreignKeyName="SOME_TABLE_FK"/>
</not>
<not>
<foreignKeyConstraintExists foreignKeyTableName="SOME_TABLE" foreignKeyName="SOME_TABLE_1_FK"/>
</not>
</preConditions>
当我使用 Liquibase 脚本升级现有数据库时(数据库从未被 Liquibase 升级),出现以下错误。
liquibase.exception.MigrationFailedException: Migration failed for change set ../master.xml::5::ray.chen:
Reason: liquibase.exception.DatabaseException: ORA-02275: such a referential constraint already exists in the table
[Failed SQL: ALTER TABLE CRDM_RCHEN.SOME_TABLE ADD CONSTRAINT SOME_TABLE_FK FOREIGN KEY (COLUMN_2) REFERENCES CRDM_RCHEN.SOME_OTHER_TABLE (COLUMN_1)]
at liquibase.changelog.ChangeSet.execute(ChangeSet.java:605)
at liquibase.changelog.visitor.UpdateVisitor.visit(UpdateVisitor.java:51)
at liquibase.changelog.ChangeLogIterator.run(ChangeLogIterator.java:79)
at liquibase.Liquibase.update(Liquibase.java:214)
at liquibase.Liquibase.update(Liquibase.java:192)
at liquibase.integration.commandline.Main.doMigration(Main.java:1126)
at liquibase.integration.commandline.Main.run(Main.java:184)
at liquibase.integration.commandline.Main.main(Main.java:103)
我仔细检查了 Liquibase 脚本和数据库,数据库中已经存在名为 SOME_TABLE_1_FK 的外键。根本原因应该是 Liquibase 脚本将添加一个名为 SOME_TABLE_FK 的外键,但一个名为 SOME_TABLE_1_FK[=28 的外键=] 已经存在,具有相同的参考详细信息和不同的名称。似乎数据库不允许 2 个名称不同但引用详细信息相同的外键。
对于这个问题,您有什么解决方案或想法吗?谢谢
这是相关的 Liquibase 脚本。我使用foreignKeyConstraintExists前置条件检查外键SOME_TABLE_FK是否存在,如果不存在则添加;但是如果存在具有相同引用详细信息但不同名称的外键(上述情况),将执行变更集并发生上述错误。
<changeSet author="ray.chen" id="5">
<preConditions onFail="MARK_RAN">
<not>
<foreignKeyConstraintExists foreignKeyName="SOME_TABLE_FK" />
</not>
</preConditions>
<addForeignKeyConstraint constraintName="SOME_TABLE_FK" baseTableName="SOME_TABLE" baseColumnNames="COLUMN_2" referencedTableName="SOME_OTHER_TABLE" referencedColumnNames="COLUMN_1" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" />
</changeSet>
liquibase提供的foreignKeyConstraintExists
需要通过foreignKeyName
。为了检查是否有没有名称的外键,您需要编写自定义前提条件。下面是一个例子:
<preConditions onFail="MARK_RAN">
<not>
<customPrecondition className="com.ctp.liquibase.ForeignKeyExistsPrecondition">
<param name="schemaName" value="MYSCHEMA"/>
<param name="tableName" value="TABLE"/>
<param name="columnName" value="COLUMN"/>
<param name="foreignTableName" value="FTABLE"/>
</customPrecondition>
</not>
</preConditions>
以上将检查 table 上的列是否具有针对外部 table 的外键约束。
您可以找到更多 here。
为什么不只检查 both/all 个名字?
<preConditions onFail="MARK_RAN">
<not>
<foreignKeyConstraintExists foreignKeyTableName="SOME_TABLE" foreignKeyName="SOME_TABLE_FK"/>
</not>
<not>
<foreignKeyConstraintExists foreignKeyTableName="SOME_TABLE" foreignKeyName="SOME_TABLE_1_FK"/>
</not>
</preConditions>