使用复杂的WHERE语句更新Liquibase中的行

时间:2013-03-11 16:19:46

标签: sql oracle10g foreign-keys foreign-key-relationship liquibase

我之前从未使用过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更新运行没有错误,但是当我看到数据库之后,没有任何改变。有没有人对我如何解决这个问题?

1 个答案:

答案 0 :(得分:8)

我终于弄明白了问题所在。变更集本身实际上没有问题。当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>