Does LiquiBase generate invalid SQL? - sql

For my MySql database I have a LiquiBase changeset that looks like this:
<changeSet id="ddl update tables : modify datatype for MY_TABLE.STATE_ABBREV" author="xxx">
<preConditions onFail="MARK_RAN" onFailMessage="Column MY_TABLE.STATE_ABBREV doesn't exists.">
<and>
<tableExists tableName="MY_TABLE"/>
<columnExists tableName="MY_TABLE" columnName="STATE_ABBREV"/>
</and>
</preConditions>
<update tableName="MY_TABLE">
<column name="STATE_ABBREV" value="AS"/>
<where>AGU
</where>
</update>
</changeSet>
This will result in
UPDATE MY_TABLE SET STATE_ABBREV = 'AS' WHERE AGU;
This does not look like valid ANSI SQL. Is this a LiquiBase bug or does LiquiBase do anything with this SQL before submitting to the database?
How can I tell LiquiBase to generate well-formed ANSI SQL?

Related

Liquibase sql generated error with column comments?

When I add a new column comment , liquibase give me an error sql. How can I fix it ?
xml like :
<databaseChangeLog xxxxxxxx>
<changeSet author="root (generated)" id="1574189348049-1">
<setColumnRemarks columnName="nickname" remarks="nickname" tableName="t_user"/>
</changeSet>
</databaseChangeLog>
sql like :
ALTER TABLE testdb.t_user COMMENT = 'nickname';

liquibase agnostic insert with sequence

I want to create a new insert changeset in liquibase using a sequence to populate the id field. Is there any way to make it database agnostic for Oracle an Postgres?
This is the oracle way:
<changeSet author="XX" id="XX">
<insert tableName="NODO_MENU">
<column name="ID" defaultValueSequenceNext="SEQ_NODO_MENU" />
<column name="CODIGO" value="ABC" />
<column name="ORDEN" value="0" />
</insert>
<rollback>
<delete tableName="NODO_MENU">
<where>CODIGO = 'ABC'</where>
</delete>
</rollback>
</changeSet>
It doesn´t work in postgres:
[Failed SQL: INSERT INTO public.NODO_MENU (ID, CODIGO, ORDEN) VALUES (SEQ_NODO_MENU.NEXTVAL, 'ABC', '0')]
To make it work in postgres I changed the column tag to:
<column name="ID" valueComputed="nextval('SEQ_NODO_MENU')" />
How can i write this changeset to make it work in Oracle an Postgress?
You can write two separate changesets. One for Postgres, one for Oracle.
Just add corresponding dbms preConditions to them.
As such:
<changeSet author="XX" id="XX_oracle">
<preConditions onFail="MARK_RAN">
<dbms type="oracle"/>
</preConditions>
<!-- your logic for Oracle-->
</changeSet>
<changeSet author="XX" id="XX_postgres">
<preConditions onFail="MARK_RAN">
<dbms type="postgresql"/>
</preConditions>
<!-- your logic for Postrgres-->
</changeSet>

How do I get liquibase to skip table creation if it already exists with liquibase formatted sql?

This is what I have
--preconditions onFail:CONTINUE
--preconditions not tableExists tableName:QRTZ_CALENDARS schemaName:dbo
CREATE TABLE dbo.QRTZ_CALENDARS (
SCHED_NAME VARCHAR (120) NOT NULL ,
CALENDAR_NAME VARCHAR (200) NOT NULL ,
CALENDAR IMAGE NOT NULL
)
GO
Background. I'm using liquibase to setup a h2 database for test cases in java.
Add a pre-Condition to your changeset for example:
<preConditions onFail="MARK_RAN">
<not>
<tableExists tableName="Table_name"/>
</not>
</preConditions>
<createTable tableName="Table_name" >
<column name="column1" type="NUMBER(20,0)"/>
</createTable>
At the moment "formatted SQL" changelogs only support the "SQL check" precondition.
Example:
--preconditions onFail:HALT onError:HALT
--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM my_table
Info source (and updates): https://docs.liquibase.com/concepts/changelogs/preconditions.html
If more complicated preconditions are required -- one could try moving to a non-SQL Liquibase format, i.e. XML or JSON

How to build a WHERE-clause in a LiquiBase changeset

How do I have to define a changeset in 'LiquiBase' notation for updating a table column whith an AND-ed WHERE-clause:
<changeSet id="ddl update tables : modify datatype for MY_TABLE.STATE_ABBREV" author="xxx">
<preConditions onFail="MARK_RAN" onFailMessage="Column MY_TABLE.STATE_ABBREV doesn't exists.">
<and>
<tableExists tableName="MY_TABLE"/>
<columnExists tableName="MY_TABLE" columnName="STATE_ABBREV"/>
</and>
</preConditions>
<update tableName="MY_TABLE">
<column name="STATE_ABBREV" value="AS"/>
<where>AGU /***AND STATE_ID=3***/ ??????????????????
</where>
</update>
</changeSet>
What you put in the <where> tag is simply appended to the end of the UPDATE statement after a " WHERE ". You can put anything in the where tag that you would normally put in SQL.
Example:
<changeSet id="ddl update tables : modify datatype for MY_TABLE.STATE_ABBREV" author="xxx">
<preConditions onFail="MARK_RAN" onFailMessage="Column MY_TABLE.STATE_ABBREV doesn't exists.">
<and>
<tableExists tableName="MY_TABLE"/>
<columnExists tableName="MY_TABLE" columnName="STATE_ABBREV"/>
</and>
</preConditions>
<update tableName="MY_TABLE">
<column name="STATE_ABBREV" value="AS"/>
<where>STATE_ABBREV IS NULL AND STATE_ID=3</where>
</update>
</changeSet>

Update type of a column in liquibase

I want to update the type of a column named "password". At the moment it has type NVARCHAR(40) and I want it to be of type NVARCHAR(64). This is what I did:
<changeSet id="1 - change password length" author="chris311">
<update tableName="tablename">
<column name="password" type="NVARCHAR(64)"/>
</update>
</changeSet>
What else is there to do? Because this obviously does not change anything in the DB.
You're using the wrong refactoring operation. Try modifyDataType
<changeSet id="increase-password-length" author="martin">
<modifyDataType tableName="tablename" columnName="password" newDataType="NVARCHAR(64)"/>
</changeSet>
You can check out http://www.liquibase.org/documentation/changes/modify_data_type.html for more documentation
Or you can do by using sql tag:
<changeSet author="liquibase-sql" id="example-sql" context="migrate">
<sql dbms="mysql">
ALTER TABLE tablename MODIFY COLUMN password NVARCHAR(64)
</sql>
</changeSet>