Liquibase Insert computedvalue with sql multiple row - sql

I want to insert multiple rows to the xxx_table with liquibase.
<changeSet id="XXX" author="XXX">
<comment>Add default values to xxx_table table</comment>
<insert tableName="xxx_table">
<column name="group_id"
valueComputed="(SELECT group_id FROM subscriber)"/>
<column name="business_name"
valueComputed="(SELECT business_name FROM subscriber)"/>
<column name="created_stamp" valueComputed="CURRENT_TIMESTAMP"/>
<column name="last_updated_stamp" valueComputed="CURRENT_TIMESTAMP"/>
</insert>
<rollback/>
</changeSet>
Liquibase script fails because more than one row is returned from '(SELECT business name FROM subscriber)'. How can I insert multiple raw to a table?

Related

How to copy the the data from one Table to another Table Using Liquibase scripts

I want to know the solution for the below Test ( to copy the the data from one Table to another Table) using Liquibase a part of Corda.
Case: As part of I want to create a new table into an existing database which has already a table called TableA (which has id, name, value columns) which has some data init, I have created a TableB (which has same id, name, value columns) and I wanted to copy the data from TableA to TableB.
For that I had used the following liquibase script as suggested here in Liquibase and In-order to test I had connected to PostgreSQL DB and connected schema called "corda_schema" which has the tables.
<changeSet author="liquibase.corda" id="update-table">
<update schemaName="corda_schema" tableName="TableB">
<column name="id" valueComputed="(SELECT id from TableA)"/>
<column name="name" valueComputed="(SELECT name from TableA)"/>
<column name="value" valueComputed="(SELECT value from TableA)"/>
</update>
</changeSet>
I was getting the following error when I tried with the Liquibase update script
Error: liquibase.corda failed
Error: schema "CORDA_SCHEMA" not found in SQL statement
If I don't given the schema name in update like this
<update tableName="TableB">
<column name="value" valueComputed="(SELECT value from TableA)"/>
</update>
the Liquibase is searching in the Public schema for TableA and I get this error:
Error: liquibase.corda failed Error: schema "PUBLIC" not found in SQL statement`
And also I tried this Liquibase script changeSet by creating the table itself I tried to update data, this changeSet is running and table is created but data is not copied.
<changeSet author="liquibase.corda" id="update-table">
<createTable schemaName = "corda_schema" tableName="TableB">
<column name="id" valueComputed= "(SELECT id FROM TableA)"/>
</createTable>
</changeSet>
Please suggest anything I am missing or any other usages that will make my test success to get the data from one table to another table.
Thanks in advance.
I would suggest to just use custom sql:
<changeSet author="liquibase.corda" id="insert-table">
<sql>
insert into corda_schema.TableB
select id,name,value from corda_schema.TableA;
</sql>
</changeSet>

How to Update a Database table column to constraint nullable='true' | Liquibase

In liquibase, I created a table, one of column is like below
<column name="identifier" type=""varchar2(50)">
<constraint nullable="false"/>
</column>
This changeset is already executed
Now I need to set this column as
<constraint nullable="true"/>
I am using MySql
If you want to change a column to nullable='true' in Liquibase, you can use the modifyColumn tag.
<modifyColumn tableName="table_name">
<column name="identifier" type="varchar2(50)">
<constraint nullable="true"/>
</column>
</modifyColumn>
Note: in Mysql, the equivalent for varchar2 is varchar; So ur modifyColumn tag should look like this:
<modifyColumn tableName="table_name">
<column name="identifier" type="varchar(50)">
<constraint nullable="true"/>
</column>
</modifyColumn>
<modifyDataType
tableName="unspecified"
columnName="identifier"
newDataType="VARCHAR(50) NOT NULL"/>

Constraints in liquibase

<?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.8.xsd">
<changeSet id="0.1.1.0" author="Bob" failOnError="true">
<createTable tableName="roles">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="name" type="varchar(1024)">
<constraints nullable="false" unique="true"/>
</column>
<column name="fam" type="varchar(1024)">
<constraints nullable="false"/>
</column>
</createTable>
<rollback>
</rollback>
I have such migrations to create a table, now I have changes and need to make other migrations. In the table, the name field is unique, I should get rid of this, that is, the name should not be unique and I need to impose a restriction on the fam. One fam should not be assigned to two roles with the same name. But roles with different names can contain the same fam. thanks in advance
If you want to add changes to the existing schema, you should keep your existing changes the way they are and write new changeSets.
So in order to implement requirement
the name field is unique, I should get rid of this
you could have used <dropUniqueConstraint> change, but it requires a constraintName attribute. But you didn't provide a uniqueConstraintName for the name's unique constraint when you were creating it, which makes implementation tricky. it's always a good practice to give your constraints and indexes names.
So, you may do the following:
create a new column, e.g. non_unique_name
copy all the data from name to non_unique_name
drop name column
rename non_unique_name column to name
The changeSets could look like this:
<changeSet id="0.1.1.1" author="Bob">
<preConditions onFail="MARK_RAN">
<tableExists tableName="roles"/>
<not>
<columnExists tableName="roles" columnName="non_unique_name"/>
</not>
</preConditions>
<comment>create a new column, e.g. non_unique_name</comment>
<addColumn tableName="roles">
<column name="non_unique_name" type="varchar(1024)">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
<changeSet id="0.1.1.2" author="Bob">
<preConditions onFail="MARK_RAN">
<tableExists tableName="roles"/>
<columnExists tableName="roles" columnName="non_unique_name"/>
<columnExists tableName="roles" columnName="name"/>
</preConditions>
<comment>copy all the data from name to non_unique_name</comment>
<update tableName="roles">
<column name="non_unique_name" valueComputed="name"/>
</update>
</changeSet>
<changeSet id="0.1.1.3" author="Bob">
<preConditions onFail="MARK_RAN">
<tableExists tableName="roles"/>
<columnExists tableName="roles" columnName="name"/>
</preConditions>
<comment>drop name column</comment>
<dropColumn tableName="roles" columnName="name"/>
</changeSet>
<changeSet id="0.1.1.4" author="Bob">
<preConditions onFail="MARK_RAN">
<tableExists tableName="roles"/>
<columnExists tableName="roles" columnName="non_unique_name"/>
</preConditions>
<comment>rename non_unique_name column to name</comment>
<renameColumn tableName="roles" oldColumnName="non_unique_name" newColumnName="name"
columnDataType="varchar(1024)"/>
</changeSet>
And in order to implement the requirement:
One dealer should not be assigned to two roles with the same name. But
roles with different names can contain the same dealer.
You may use <addUniqueConstraint> change, with it you can add composite unique constraints. The changeSet could look like this:
<changeSet id="0.1.1.5" author="Bob">
<preConditions onFail="MARK_RAN">
<tableExists tableName="roles"/>
<columnExists tableName="roles" columnName="dealer"/>
<columnExists tableName="roles" columnName="name"/>
</preConditions>
<comment>add unique constraint for roles.dealer and roles.name</comment>
<addUniqueConstraint tableName="roles" columnNames="dealer, name"
constraintName="roles_dealer_name_unique" />
</changeSet>

How add specific type column by liqiubase

Postgresql has type INTERVAL for column. But I didn`t found simple way to create table with such column.
I have solution with two steps:
1. Create table by liquibase changeSet.
2. Use changeSet with sqlFile. Sql file contain sql for add column.
Example changeSet:
<changeSet author="author" id="add-testmy-table-v1">
<preConditions onFail="MARK_RAN">
<not>
<tableExists tableName="testmy"/>
</not>
</preConditions>
<createTable tableName="testmy">
<column autoIncrement="true" name="id" type="BIGSERIAL">
<constraints primaryKey="true" primaryKeyName="PK_testmy"/>
</column>
<column name="created_at" type="TIMESTAMP(6) WITHOUT TIME ZONE"/>
<column name="employee_id" type="BIGINT"/>
</createTable>
</changeSet>
<changeSet author="liquibase-docs" id="sql-example">
<sqlFile dbms="postgresql" encoding="utf8" path="testmy.sql" relativeToChangelogFile="true"/>
</changeSet>
testmy.sql file contain:
ALTER TABLE testmy
ADD COLUMN began_at INTERVAL ,
ADD COLUMN ended_at INTERVAL ;
Could anyone show another variant to solve such problem?

Liquibase createIndex column order

I'm trying to use Liquibase for our project. We mainly use Oracle database and some other database less often. I'm trying to figureout how to specify column order in case of indexes. Below is a typical create index change set.
<createIndex indexName="PK_xxxxxxx" tableName="xxxxx" unique="true">
<column name="column_1"/>
<column name="column_2"/>
<column name="column_3"/>
</createIndex>
When it comes to performance and application scalablity, column order in index matters a lot. Can you please guide me if there is a way to specify same while creating index?
PS: As per column tag documentation, attributes afterColumn, position exists and they are applicable only for create table I assume. Here is what documentation says about it.
If used in an 'addColumn' command, this attribute allows you to control where in the table column order the new column goes. Only one of beforeColumn, afterColumn or position are allowed. Since 3.1
Liquibase will use the order of columns as listed in the createIndex tag - very much like the DBMS uses the order specified in the create index statement.
The following changeset:
<changeSet author="arthur" id="1">
<createTable tableName="foo">
<column name="col_1" type="integer"/>
<column name="col_2" type="integer"/>
<column name="col_3" type="integer"/>
</createTable>
<createIndex indexName="ix_one" tableName="foo">
<column name="col_1"/>
<column name="col_2"/>
<column name="col_3"/>
</createIndex>
<createIndex indexName="ix_two" tableName="foo">
<column name="col_3"/>
<column name="col_2"/>
<column name="col_1"/>
</createIndex>
<createIndex indexName="ix_three" tableName="foo">
<column name="col_2"/>
<column name="col_3"/>
<column name="col_1"/>
</createIndex>
</changeSet>
will produce the following statements (when e.g. run with updateSQL):
CREATE TABLE public.foo (col_1 INT, col_2 INT, col_3 INT);
CREATE INDEX ix_one ON public.foo(col_1, col_2, col_3);
CREATE INDEX ix_two ON public.foo(col_3, col_2, col_1);
CREATE INDEX ix_three ON public.foo(col_2, col_3, col_1);