Set initial value in liquibase with postgresql database - sql

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

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>

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

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>

Set max column value as sequence start value with liquibase tags

I wonder if it possible to get maximum column value from a certain table and set it as start sequence value with no pure sql. The following code doesn't work:
<property name="maxId" value="(select max(id)+1 from some_table)" dbms="h2,mysql,postgres"/>
<changeSet author="author (generated)" id="1447943899053-1">
<createSequence sequenceName="id_seq" startValue="${maxId}" incrementBy="1"/>
</changeSet>
Got an error:
Caused by: liquibase.parser.core.ParsedNodeException: java.lang.NumberFormatException: For input string: "${m"
I've tried it with no parentheses around select ... etc. with the same result.
So it's not possible to use computed value as start sequence value?
So, such a solution worked for me:
<changeSet author="dfche" id="1448634241199-1">
<createSequence sequenceName="user_id_seq" startValue="1" incrementBy="1"/>
</changeSet>
<changeSet author="dfche" id="1448634241199-2">
<sql dbms="postgresql">select setval('user_id_seq', max(id)+1) from jhi_user</sql>
<sql dbms="h2">alter sequence user_id_seq restart with (select max(id)+1 from jhi_user)</sql>
</changeSet>
For postgres correct sql dbms sentence is:
<sql dbms="postgresql">select setval('some_table_id_seq', (select max(id)+1 from some_table), false)</sql>

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.