我以前从未使用过Liquibase,只是不知道如何解决这个问题。我最近加入的项目是一个旧项目的翻拍版,所以我们必须使用一个旧数据库,它有一个糟糕的设计模式。数据库不使用外键约束,因此仍有条目指向已不存在的条目。在我的案例中,是一名医生在一家银行拥有一个数据库中不存在的银行账户。到目前为止,我的团队处理这些问题的方式是用NULL覆盖ID。所以,基本上,当银行不存在时,我要做的是将所有银行账户ID设置为NULL。我为完成这项任务而编写的SQL代码如下:
UPDATE DOCTOR SET FK_BANKID = NULL WHERE FK_BANKID NOT IN (SELECT ID FROM BANK);
我被告知要将该修复程序集成到我们的Liquibase变更集中,但我就是不知道如何做到。这就是我迄今为止所做的:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet id="remove_fk_bankid" author="v7">
<update tableName="DOCTOR">
<column name="FK_BANKID" value="NULL" />
<where>FK_BANKID NOT IN (SELECT ID FROM BANK)</where>
</update>
</changeSet>
</databaseChangeLog>
Liquibase更新运行时没有错误,但当我稍后查看数据库时,没有任何变化。有人能告诉我如何解决这个问题吗?
我终于弄清楚问题出在哪里了。实际上变更集本身没有问题。当Liquibase更新数据库时,它会记录数据库中的所有变更集,这样已经执行的变更集就不会再执行了。Liquibase保存变更集内容的散列,以便已更改的变更集将再次执行。实际的问题是,当我第一次执行变更集时,数据库是干净的,因为我使用以下SQL命令手动执行:UPDATE DOCTOR SET FK_BANKID = NULL WHERE FK_BANKID NOT IN (SELECT ID FROM BANK);
。之后,我更改了一个医生行,并将银行ID设置为一个不存在的银行,然后再次执行变更集,只是为了测试变更集是否真的有效。由于Liquibase的日志中有我的变更集,所以它没有再次执行。因此,我看不到数据库中的更改。当我回滚所有更改并再次更新数据库时,我注意到了这一点。
为了使变更集完整,我还必须定义回滚,因为Liquibase无法自动回滚行更新。由于银行账户的ID永远丢失,我只添加了一个空的回滚命令:
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet id="remove_fk_bankid" author="v7">
<update tableName="DOCTOR">
<column name="FK_BANKID" value="NULL" />
<where>FK_BANKID NOT IN (SELECT ID FROM BANK)</where>
</update>
<rollback>
</rollback>
</changeSet>
</databaseChangeLog>