我以前从未使用过 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>
关于sql - 使用复杂的 WHERE 语句更新 Liquibase 中的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15343481/