Question

I'm using Liquibase for versioning an existing database, so I'm using

liquibase \
  --logLevel=debug \
  --driver=com.mysql.jdbc.Driver \
  --classpath=lib/mysql-connector-java-5.1.30.jar \
  --url="jdbc:mysql://127.0.0.1:3306/schema" \
  --username=user \
  --password=pass \
  --diffTypes="data" \
  --changeLogFile="./data.xml" generateChangeLog

for generating the changeset xml.

This works, but the problem is when I'm trying to run those generated changesets. I get

Cannot add or update a child row: a foreign key ...' because the exported order of changeset does not take into account the foreign keys.

My question is: Is there a command option or something that can generate the changeset in the right order or should I manually reorder the changesets to get the desired result?

Update:

Normally, the foreign keys should be and are created after the foreign key. But, in our systems, the core application creates the structure of the database and multiple client applications are populating the database with their own private data in the same database. And when we're generating the data, the data changesets are generated in the alphabetical order of the tables in the database, which may the foreign key constraints. We managed to manually arrange the changesets, but I would like to know if there is a nicer workaround for this particular situation.

Was it helpful?

Solution

So the problem is not with the order of types of changes (tables, then data then FKs) but that you are using just the generated data insets with an existing table and FK structure? Liquibase does not even try to figure out how rows depend on each other as it gets nearly impossible in the general case.

The easiest solution is to disable FK checks before inserting and re-enable them after. How you do that depends on your database, but you can include something like:

<changeSet id="disable-keys" author="x" runAlways="true">
    <sql>SET FOREIGN_KEY_CHECKS=0;</sql>
</changeSet>

before your <insert> tags and

<changeSet id="enable-keys" author="x" runAlways="true">
    <sql>SET FOREIGN_KEY_CHECKS=1;</sql>
</changeSet>

after them.

OTHER TIPS

There is no way to control the order. However, it should be generating it with creation then data insert than foreign key creation. Are you running the newest 3.1.1 version?

You can always reorder the changelog as well. You should consider the output of generateChangeLog as saving you from typing in a changeLog for an existing database and there is nothing wrong with fixing up what was generated if it is not quite right. The main functionality of Liquibase is tracking executed chagneSets and so is limitations to the "snapshot" functionality including perhaps ordering of generated chagneSets.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top