changeset

The changeset tag is a unit of change that Liquibase executes on a database and which is used to group database Change Types together. A list of changes created by multiple changesets are tracked in a changelog.

A changeset is uniquely tagged by both an author and an id attributes (author:id), as well as the changelog file path. The id tag is only used as an identifier, it does not direct the order that changes are run and does not have to be an integer. If you do not know or do not want to save the actual author, use a placeholder value such as UNKNOWN. To execute the changeset, you must include both author and id.

<?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"  
  xmlns:pro="http://www.liquibase.org/xml/ns/pro"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.0.xsd
      http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-3.8.xsd">  
    <changeSet id="1" author="bob">  
        <comment>A sample change log</comment>  
        <createTable/> 
    </changeSet>  
    <changeSet id="2" author="bob" runAlways="true">  
        <alterTable/>  
    </changeSet>  
    <changeSet id="3" author="alice" failOnError="false" dbms="oracle">
        <alterTable/>  
    </changeSet>  
    <changeSet id="4" author="alice" failOnError="false" dbms="!oracle">
        <alterTable/>  
    </changeSet>  

</databaseChangeLog>

Running the changeset

As Liquibase uses the DATABASECHANGELOG table, it reads the changesets in order and, for each one, checks the DATABASECHANGELOG table to see if the combination of id/author/filepath has been run.

If it has been run, the changeset will be skipped unless there is a runAlways tag set to true in that changeset. After all the changes in the changesets are run, Liquibase will insert a new row with the id/author/filepath along with an MD5Sum of the changeset in the DATABASECHANGELOG.

Note: filepath is the path that defines the changeLogFile attribute. Even if the same file is referenced with a different path, that is considered a different file unless the logicalFilePath is defined.

Liquibase attempts to execute each changeset in a transaction that is committed at the end, or rolled back if there is an error. Some databases will auto-commit statements which interferes with this transaction setup and could lead to an unexpected database state. Therefore, it is best practice to have just one change per changeset unless there is a group of non-auto-committing changes that you want to apply as a transaction such as inserting data.

Available attributes

id Specifies an alpha-numeric identifier. Required
author Specifies the creator of the changeset. Required
dbms Specifies the type of a database for which that changeset will be used. When the migration step is running, it checks the database type against this attribute.

Note: For more information about database type names, see Supported databases page.

Also, you can do the following:
  • List multiple databases separated by commas.
  • Specify that a changeset is not applicable to a particular database type by prefixing it with !.
  • Add the keywords all and none.
runAlways Executes the changeset on every run, even if it has been run before.
runOnChange Executes the changeset the first time and each time the changeset has been changed.
Contexts Controls whether a changeset is executed depending on runtime settings. Any string can be used for the context name and they are checked case-insensitively.
Labels Controls whether a changeset is executed depending on runtime settings. Any string can be used for the label name and they are checked case-insensitively.
runInTransaction

Specifies whether the changeset can be ran as a single transaction (if possible). Default value is true.

Warning: If this attribute is set to false and an error occurs part way through running a changeset that contains multiple statements, the Liquibase DATABASECHANGELOG table will be left in an invalid state. Since 1.9

failOnError Defines whether the migration will fail if an error occurs while executing the changeset. Default value is true.
objectQuotingStrategy Controls how object names are quoted in the generated SQL or used in calls to the database. Different databases do different things to the names of objects. For example, Oracle converts everything to uppercase (unless quoted). There are three possible values. The default value is LEGACY.
LEGACY - the same behavior as in Liquibase 2.0
QUOTE_ALL_OBJECTS - every object gets quoted. For example: person becomes "person".
QUOTE_ONLY_RESERVED_WORDS - reserved keywords and invalid column names are quoted.
runOrder Overrides the order in the changelog from where the changeset with the runOrder="first|last" will be run. It is typically used when you want a changeset to be always executed after everything else but don’t want to keep moving it to the end of the changelog. Setting the runOrder to last will automatically move it in the final changeset order.Since 3.5
created Stores dates, versions, or any other string of value without using remarks (comments) attributes. Since 3.5
ignore Ignores the changeset from the execution. Since 3.6
logicalFilePath Overrides the file name and path when creating the unique identifier of changesets. Required when moving or renaming changelog.

Available sub-tags

comment Specifies the description of the changeset. XML comments will provide the same benefit. Future releases of Liquibase may be able to make use of <comment> tag comments to generate documentation.
preConditions Must be passed before the changeset will be executed. It is typically used for doing a data sanity check before doing something unrecoverable such as a dropTable.Since 1.7

Note: For more information, see Preconditions.

<Any Refactoring Tag(s)> Specifies the database change(s) to run as part of the changeset (Change Types).
validCheckSum Adds a checksum that is considered valid for this changeset, regardless of what is stored in the database. It is primarily used when you need to change a changeset and don't want errors thrown on databases on which it has already been run (not a recommended procedure). Special value "1:any" will match to any checksum and will not execute the changeset on ANY change. Since 1.7
rollback Specifies SQL statements or Change Type tags that describe how to rollback the changeset.

Note: For more information, see Liquibase Rollback Workflow.

The rollback tag

The rollback tag describes how to roll back a change using SQL statement(s), change tags, or a reference to a previous changeset.

Rollback tag examples

You can have a plain SQL in the content part of the <rollback> element. The text in the element is treated as an <sql> change with stripComments set to true, splitStatements set to true, and endDelimiter set to ;.

<changeSet id="1" author="bob">  
    <createTable tableName="testTable">  
    <rollback>
        drop table testTable
    </rollback> 
</changeSet>

Also, you can have any type of change in the <rollback> element.

<changeSet id="1" author="bob"> 
    <createTable tableName="testTable">  
    <rollback>  
        <dropTable tableName="testTable"/> 
    </rollback>  
</changeSet>

The following example shows how a <rollback> element can be referred to another changeset. So, to roll back the changeset with id="2", apply the changeset with id="1".

<changeSet id="2" author="bob">  
    <dropTable tableName="testTable"/> 
    <rollback changeSetId="1" changeSetAuthor="bob"/> 
</changeSet>

changeset checksums

When Liquibase reaches a changeset, it computes a checksum and stores it in the DATABASECHANGELOG table. The value of storing the checksum for Liquibase is to know if something has been changed in the changeset since it was run.

If the changeset has been changed since it was run, Liquibase will exit the migration with an error message like Validation failed: change set check sums <changeset identifer> was: <old checksum> but is now: <newchecksum>. This is because Liquibase cannot identify what was changed and the database may be in a state different than what the changelog is expecting. If there was a valid reason for the changeset to be changed and you want to ignore this error, there are two options.

Note: You can also use the clearCheckSums command to resolve the checksum error, however, it will clear the entire column of checksums in your DATABASECHANGELOG table.

The manual update of the DATABASECHANGELOG table

The first option is to manually update the DATABASECHANGELOG table so that the row with the corresponding id/author/filepath has a null value for the checksum. You would need to do this for all environments where the changeset has been deployed. The next time you run the Liquibase update command, it will update the checksum value to the new correct value.

The <validCheckSum> attribute

The second option is to add a <validCheckSum> element to the changeset. The text contents of the element should contain the old checksum from the error message.

The runOnChange attribute

Checksums are also used in conjunction with the runOnChange changeset attribute. There are times you may not want to add a new changeset because you only need to know about the current version, but you want this change to be applied whenever it is updated. For example, you can do this with stored procedures.

If you copy the entire text of the stored procedure to a new changeset each time you make a change, you will not only end up with a very long changelog, but you will lose the merging and diffing power of your source control. Instead, put the text of the stored procedure in a changeset with a runOnChange="true" attribute. The stored procedure will be re-created when there is a change to the text of it.

Note: For more information, see runOnChange changeset attribute.

Related Links