What is property substitution?

Liquibase allows a dynamic substitution of properties in your changelog. The tokens to replace in your changelog are described using the ${property-name} syntax.

Liquibase allows a dynamic substitution of properties in your changelog. The tokens to replace in your changelog are described using the ${property-name} syntax.

Uses

By substituting values for replacement tokens in the format of ${property-name}, you can use the same changesets to reflect small environmental changes.

For example, your tablespace name in Oracle may differ from environment to environment, but you want to only write one create table changeset that can be used in all of your environments.

Using property substitution in your changelog

You can set property values in Liquibase in several ways. Liquibase assigns these values in the following order:

  • As an attribute passed to your Liquibase runner. See the Ant, Maven, or Servlet Listener documentation for more information on how to pass them.

  • As a JVM system property. See JAVA_OPTS Environment Variable for more information.

  • As an environment variable.

  • As a CLI attribute, if executed from the command line. Use the syntax liquibase <command.name> -D<property.name>=<property.value>. On Windows, surround the property name in quotation marks if it contains a dot. For example: -D"property.name"=value.

  • In the parameters block (property element of the changelog file itself).

Once a property has been set, it cannot be changed. Also, only the first definition is used, others are skipped.

Note: If the content of ${property-name} does not match a property, it is left as-is and it is not removed. The supported format includes alphanumeric characters, +, -, . , and _.

Defining properties with contexts

You can define multiple values for the same property by associating each with a specific context. Looking at the following example code, when Liquibase runs with --context=DEV, the ${tblsp.name} token will be replaced with tblsp_cms_dev. This lets you safely use a single changelog across all environments.

Be sure to place <property> tags at the beginning of the changelog, before any <changeSet> definitions.

<property name="tblsp.name" value="tblsp_cms_dev" context="DEV"/> <property name="tblsp.name" value="tblsp_cms_test" context="TEST"/> <property name="tblsp.name" value="tblsp_cms_qa" context="QA"/> <property name="tblsp.name" value="tblsp_cms" context="UAT,PROD"/>

Example Changelog with context-based properties

The first 3 lines of this example changelog provide an additional example of context-based properties being used.

<property name="TS_NAME" value="DEV_TS" context="DEV"/> <property name="TS_NAME" value="TEST_TS" context="TEST"/> <property name="TS_NAME" value="PROD_TS" context="PROD"/>

Example Changelog with context-based properties

The first 3 lines of this example changelog provide an additional example of context-based properties being used.

<changeSet id="27" author="liquibase">
  <createTable tableName="actor" tablespace="${TS_NAME}">
    <column name="id" type="INTEGER"/>
    <column name="firstname" type="VARCHAR(255)"/>
    <column name="lastname" type="VARCHAR(255)"/>
    <column name="twitter" type="VARCHAR(15)"/>
  </createTable>
</changeSet>

Example CLI and properties file usage

The following examples show different ways to assign values to your changelog properties depending on how you're running Liquibase. Choose the approach that best fits your workflow or automation needs.

Liquibase Properties file: Useful for teams or CI/CD pipelines requiring a reusable, version-controlled configuration.

parameter.TS_NAME=DEV_TS

Command-line (CLI) Attribute: This attribute is Good for quick, one-off executions or scripting where you want to override values dynamically at runtime.

liquibase update -DTS_NAME=DEV_TS

Environment Variable: Ideal for environments where the OS or deployment system securely manages sensitive values (like credentials or paths). Especially common in containerized or cloud environments.

export TS_NAME=DEV_TS

sql and sqlFile

You can use property substitution with the sql and sqlFile Change Types. Note that Liquibase obtains the checksum of a sql changeset after substituting any properties you specify. However, it obtains the checksum of a sqlFile changeset before substituting the properties in the external SQL file.

This affects the behavior of attributes like runOnChange. For example, suppose you set an environment variable ENV_EXAMPLE=value and you use property substitution for ENV_EXAMPLE in two changesets: sql and sqlFile. If you deploy your changes with the update command, ENV_EXAMPLE is substituted for the value you set. Suppose each changeset is also labeled with runOnChange=true, so if you run the update command, the changesets rerun only if their contents have changed since the last deployment. If you then set ENV_EXAMPLE=new_value and run update, only the sql changeset runs a second time.

Nested properties

Name

Description

Required for

Supports

Multiple allowed?

<property>

Defined before

changeset

s

in the

changelog

Substituting portions of a

changeset

during runtime

All supported

changeset

tokens

No. Property names are unique and can only be set one.

Available attributes

Attribute

Description

name

The name of the parameter.

Required if file is not set

value

The value of the property. Required if file is not set

file

The name of the file from which the properties should be loaded. It will create a property for all properties in the file. The content of the file must follow the Java properties file format.

relativeToChangelogFile

The relativeToChangelogFile attribute is used in conjunction with the file An attribute to allow Liquibase to find the referenced file without having to configure the search path. The default for relativeToChangelogFile remains FALSE for backwards compatibility.

context

Contexts in which the property is valid. Expected as a comma-separated list.

dbms

Specifies which database type(s)a changeset is to be used for. See valid database type names on dbms. Separate multiple databases with commas. Specify that a changeset does not apply to a particular database type by prefixing it with !. The keywords all and none are also available.

global

Boolean. The attribute defines whether the property is global or limited to the actual DATABASECHANGELOG.

Default: true

Property substitution syntax

--liquibase formatted sql

--changeset example:1
CREATE TABLE ${schema.name}.person
( id int primary key,
  first_name varchar(50) NOT NULL,
  last_name varchar(50) NOT NULL
)