I want to add check constraint to BLOB type column which stores JSON data, in CREATE Table script in liquibase(version 3.3.5, database -Oracle 12C). but it does not compile. Can anyone please explain what is the right syntax to add constraint which ensures only JSON type data would be inserted. I followed this question
Plain sql : CONSTRAINT ensure_json CHECK (po_document IS JSON))
But not sure what is liquibase equivalent for this.
PostgreSQL Check Constraint in Liquibase
<changeSet id="Change_id" author="xqz">
<createTable tableName="table_name">
<column name="pkey" type="int">
<constraints primaryKey="true"/>
</column>
<column name="table2_pkey" type="int">
<constraints nullable="false"/>
</column>
<column name="name" type="varchar(100)">
<constraints nullable="false"/>
</column>
<column name="filters" type="BLOB">
<constraints checkConstraint="ensure_json CHECK (filters IS JSON)" />
</column>
</createTable>
</changeSet>
If I add constraint to filters column, build fails, If I remove it, build is successful. What am I doing wrong. I could not find syntax for it in liquibase docs.
You cannot define check constraints in liquibase, for aditional information see this forum entry.
You'll have to use an <sql> tag like
<sql dbms=oracle>
CREATE TABLE table_name (
pkey integer PRIMARY KEY,
table2_pkey integer NOT NULL,
name varchar(100) NOT NULL,
flter blob CONSTRAINT ensure_json CHECK (filters IS JSON)
)
</sql>
Should work just the same, except that you have to add your own <rollback> tag.
Related
The Setup
I am using Liquibase to manage my project's migrations.
I have several tables with several sets of seed data.
Each seeded table has a changeset to create the table, followed by a changeset to load the seed data. The seeds are being loaded using loadUpdateData. This is a smart method that will load seed data from a CSV, if the CSV content is edited it will make the appropriate edits directly.
The seed ChangeSets are in a separate ChangeLog that is always run after the core ChangeLog. This way the seed files can always reflect the correct table structure.
The Problem
I need to drop a table that has seed data. The loadUpdateData command errors because the table no longer exists by the time it is run.
The Code
Create Table ChangeSet
<changeSet author="" id="create-table-help-items">
<createTable tableName="help_items">
<column name="help_item_id"
type="bigint">
<constraints primaryKey="true"/>
</column>
<column name="title"
type="text" />
<column name="description"
type="text" />
</createTable>
<rollback>
<dropTable tableName="help_items"/>
</rollback>
</changeSet>
Seed ChangeSet
<changeSet author="" id="seed-help-items" runOnChange="true">
<loadUpdateData file="db/seeds/help_items.csv"
primaryKey="help_items_id"
tableName="help_items" />
</changeSet>
Drop Table ChangeSet
<changeSet author="" id="remove-table-help-items">
<dropTable tableName="help_items"/>
<rollback changeSetId="create-table-help-items" changeSetAuthor=""/>
</changeSet>
The Questions
Given that it is bad practice to ever delete changesets from a changelog.
What is the right way to create seed migrations so that they don't break when the table is deleted?
Do I need to keep the seed files for tables that have been dropped?
I had the same problem and now i solved it, it works already by me.
The point is that you should set the Rollback in "Drop Table ChangeSet" correctly.
So by droping a table, you should already prepare for the situation of rollback.
<changeSet author="" id="remove-table-help-items">
<dropTable tableName="help_items"/>
<rollback>
<createTable tableName="help_items"/>
</rollback>
</changeSet>
I solved this issue by setting runAlways: false for loadUpdateData changeset. So, it doesn't fail when the table is dropped.
I am trying to populate 2 tables through csv files in liquibase.
I have one table called tenant and one another named tenant_configuration and have foreign key to tenant. First part is load tenant data:
<changeSet id="1" context="test">
<comment>Insert data for tenant table</comment>
<loadUpdateData
primaryKey="id"
file="tenant.csv"
tableName="tenant"/>
</changeSet>
Then i would like to use another csv file to populate tenant config but retrieve tenant_id from first change.
<changeSet id="2" context="test">
<comment>Insert data for tenant_db_configuration table</comment>
<loadData tableName="tenant_db_configuration"
file="tenant_db_configuration.csv"
separator="," >
<column name="tenant_id" type="NUMERIC" defaultValueComputed="(SELECT ID FROM tenant WHERE tenant_id = tenant_1)"/>
<column header="username" name="username" type="STRING"/>
<column header="password" name="password" type="STRING"/>
</loadData>
</changeSet>
Tried this but liquibase ignore the tenant_id part and shows:
[Failed SQL: INSERT INTO [dbo].[tenant_db_configuration] ([username], [password]) VALUES...
how i can retrieve that foreign key and merge with existing csv file to load data?
thanks!
As far as i know you will need to make the relation manually in the secomnd CSV file, tenant_db_configuration.csv. I mean, each row in there will need to be pointing to an existent id in the tenat Table.
If the order doesnt matters bc you trust in your csv data, You could disable the foreign key checks with a changeSet before starting to import the data.
I dunno wich DBMS are you using but with MYSQL is
<changeSet author="liquibase-docs" id="sql-example">
<sql dbms="mysql">
SET FOREIGN_KEY_CHECKS=0;
</sql>
</changeSet>
and then you can enable it after on a separate changeSet.
It's been 3 months since the question, so Hope it helps. If you solved it already, what was the solution?
I have added some new changesets in an existing changelog file and want to execute only 2 among the new inserted ones. When I give the update command in liquibase it updates all the unread changesets and updates the database. But I want to execute only 2 among these newly inserted changesets in the changelog file. Is there any way of doing this in liquibase? If yes how is it possible?
One way you could do this is to mark the relevant changesets with a label, and then use that label in your liquibase update command.
This blog post on labels describes their use.
Here is an example that matches what you described in your comment below.
changelog
<?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-3.5.xsd">
<changeSet id="1" author="steve" labels="labelOne">
<createTable tableName="tableOne">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
</column>
</createTable>
</changeSet>
<changeSet id="2" author="steve" labels="labelTwo">
<comment>Creating table "tableTwo"</comment>
<createTable tableName="tableTwo">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
</column>
</createTable>
</changeSet>
<changeSet id="3" author="steve" labels="labelThree">
<comment>Creating table "tableThree"</comment>
<createTable tableName="tableThree">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
</column>
</createTable>
</changeSet>
</databaseChangeLog>
command execution
If you wanted to update and only create table one, you would use this command (if you are using the command line, and assuming that you have a liquibase.properties file that specifies all the connection information, etc.)
liquibase --changeLogFile=changelog.xml --labels=labelOne update
If you wanted to apply two changesets, you would use a command like this:
liquibase --changeLogFile=changelog.xml --labels="labelOne and labelTwo" update
I would like to do a liquibase insert with the primary key being auto generated from the sequence defined in the database. The target database is HSQLDB.
It works to do an insert specifying a value for the primary key
<insert ...>
<column name="TAG_ID" valueNumeric="2"/>
I found this (admittedly older) conversation about it but the issue is still the same. The suggested fix doesn't work for HSQLDB.
Looking at the docs I've tried some things like
<column name="TAG_ID" defaultValueSequenceNext="TAG_ID_SEQ" />
<column name="TAG_ID" defaultValueSequenceNext="TAG_ID_SEQ.NEXTVAL" />
<column name="TAG_ID" valueComputed="TAG_ID_SEQ.NEXTVAL" />
<column name="TAG_ID" autoIncrement="true" />
but none of those put anything in the key when I do the insert (the insert fails on a null primary key).
How does one accomplish this?
HSQLDB has a setting to use Oracle syntax. You can set HSQLDB to use oracle syntax like so:
<changeSet ...
<sql dbms="hsqldb" >SET DATABASE SQL SYNTAX ORA TRUE</sql>
</changeSet>
After that, it works to do the insert like this:
<insert ...
<column name="TAG_ID" valueComputed="TAG_ID_SEQ.NEXTVAL"/>
I am using Liquibase 3.2.0 to perform an upgrade on an Oracle DB. All the existing table names in my schema are in lowercase
My problem is, when I use Liquibase to run a changeSet, the table names are generated in upper-case.
A typical entry in my changeSet looks as follows:
<changeSet author="me (generated)" id="1403006263048-2">
<createTable tableName="batch_job">
<column name="id" type="number">
<constraints nullable="false" primaryKey="true" primaryKeyName="batch_jobPK"/>
</column>
<column name="version" type="number">
<constraints nullable="false"/>
</column>
<column name="execution_time_stamp" type="timestamp">
<constraints nullable="false"/>
</column>
<column name="reference_region" type="varchar2(5)">
<constraints nullable="false"/>
</column>
<column name="trigger_description" type="varchar2(255)">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
However, the resulting table name is: BATCH_JOB
I have tried setting an attribute objectQuotingStrategy="QUOTE_ALL_OBJECTS" in the databaseChangeLog element, with no success.
Is there a way to achieve what I want? I am familiar with the advice offered in Liquibase/PostgreSQL: how to preserve table case correctly?
Any help would be much appreciated. Thanks!
It looks like a bug in how Liquibase is handling case standardization. Could you log an issue at liquibase.jira.com?
For now, the easiset approach would be to use a <modifySql> block to fix the case of the table where it is a problem. Or just fall back on the <sql> tag.
Thanks Nathan, lowercase issue is resolved by using <modifysql> as
<modifySql>
<replace replace="filter" with="FILTER"/>
</modifySql>