Liquibase: Copy column data into a new column in the same table - sql

I have a table with a column A. I am creating a new column B. B will have the same data as column A. How do I replicate the column in Liquibase? Is there some expression I can write to do the replication?

this is possible too:
<changeSet id="1" author="your_name">
<addColumn tableName="your_table">
<column name="b" type="varchar(255)"/>
</addColumn>
</changeSet>
<changeSet id="2" author="your_name">
<update tableName="your_table">
<column name="b" valueComputed="a"/>
</update>
</changeSet>

Create a new changeset where you add a new column, and then update column B using the <sql> tag:
<changeSet author="yourName" id="example">
<addColumn catalogName="db"
schemaName="public"
tableName="yourTable">
<!-- replace varchar(255) with the actual type of column A -->
<column name="B" type="varchar(255)"/>
</addColumn>
<sql>UPDATE yourTable SET B = A</sql>
</changeSet>

Related

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>

Set initial value in liquibase with postgresql database

I have a table and i need that it's ID start in 1000000.
I have this code set for liquibase:
<column name="id" type="bigint" autoIncrement="true" startWith="1000000">
<constraints primaryKey="true" nullable="false"/>
</column>
But it does not work in postgres, the generated sequence generator starts with 1.
Does anyone has any idea on this? How can i enable a table to start from a value in liquibase that works with postgresql?
Thanks in advance!
just alterSequence won't help:
<alterSequence
minValue="1000000"
sequenceName="t1_id_seq"/>
Unexpected error running Liquibase: ERROR: START value (1) cannot be
less than M INVALUE (1000000) [Failed SQL: ALTER SEQUENCE
public.t1_id_seq MINVALUE 1000000]
and according to docs you can't start sequence with alterSequence, so you have to createSequence with
<createSequence
sequenceName="seq_id"
startValue="1000000"/>
and then "assign" it as default value to your bigint column
<sql dbms="postgresql" endDelimiter=";\n" splitStatements="true"
stripComments="true">ALTER TABLE t1 ALTER COLUMN id SET DEFAULT nextval('seq_id');
</sql>
or initially use bigserial and sql to restart sequence:
<changeSet author="Vao" id="1">
<createTable tableName="t2">
<column name="id" type="bigserial">
<constraints primaryKey="true" primaryKeyName="t2_pkey"/>
</column>
</createTable>
</changeSet>
<changeSet author="Vao" id="2">
<sql dbms="postgresql" endDelimiter=";">ALTER SEQUENCE t2_id_seq restart with 1000;
</sql>
</changeSet>
Unfortunately startWith don't seems to work for postgres db.
You can use (with yaml configuration) :
- changeSet:
id: add-auto-increment-postgres
author: me
dbms: postgresql
changes:
- createSequence:
sequenceName: my_sequence
startValue: 1000
- addDefaultValue:
columnName: id
defaultValueSequenceNext: my_sequence
tableName: my_table
Thx! Drop and create new - helps
dropSequence
createSequence

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>

Convert int to value when changing datatype in column

Is it possible with liquibase to do some kind of mapping when doing a modifyDataType?
Considering the following example:
<changeSet id="1" author="me">
<createTable tableName="person">
<column name="id" type="int">
<constraints primaryKey="true" nullable="false" />
</column>
<column name="firstName" type="varchar(100)"></column>
<column name="lastName" type="varchar(100)"></column>
<column name="marital_status" type="int">
<constraints nullable="false" />
</column>
</createTable>
</changeSet>
<changeSet id="2" author="me">
<modifyDataType tableName="person" columnName="type"
newDataType="varchar(36)" />
</changeSet>
I would like in my column 'type' that the following mapping occurs:
0->single
1->married
etc..
Is this possible with liquibase? I'm using it via the command line.
I think this is not possible directly via some kind of mapping or refactoring.
One way to do this is using sql and put this into another changeset which is run right after the one that changes the data type:
<changeSet id="3" author="me">
<sql>
update person set martial_status = 'single' where martial_status = 0;
update person set martial_status = 'married' where martial_status = 1;
</sql>
</changeSet>
I just wrote this down as an idea. It is untested.
You could add a precondition to execute this changeset only if changeset with id 2 ran successful.