Liquibase for/for each operation (migrating table data) - sql

I'm using Liquibase and I need to insert data in one table, depending on the entries in another (create a foreign key reference)
Table: Entities (currently empty)
PK id
INT data
Table: Existing_table (contains data)
PK id
... data
FK entities_id (references Entities.id)
for each entry in Existing_table I need to insert a value in Entities and update entities_id in Existing_table, using the created Entities.id key.
How can I achieve this?

Couldn't find a way to make a parametrised loop, so used a temopary column for storing referenced id.
<changeSet id="add temp_column to Entities" author="">
<addColumn tableName="Entities">
<column name="temp_id" type="BIGINT"></column>
</addColumn>
</changeSet>
<changeSet author="" id="insert Existing_table keys into Entities">
<sql>
INSERT INTO Entities(type_id, temp_id)
select 1, id
from Existing_table;
</sql>
</changeSet>
<changeSet author="" id="insert entity keys into Existing_table">
<sql>
UPDATE Existing_table d set entity_id = ent.id
FROM (select id, temp_id
from Entities) ent
where ent.temp_id = d.id;
</sql>
</changeSet>
<changeSet id="drop temp_column to Entities" author="">
<dropColumn tableName="Entities"
columnName="temp_id"/>
</changeSet>
<changeSet author="" id="addNotNullConstraint Existing_table-Entities">
<addNotNullConstraint columnDataType="BIGINT"
columnName="entity_id"
tableName="Existing_table"/>
</changeSet>

Related

How to insert auto_increment in an already created table in liquibase

How to insert auto_increment in an already created table in liquibase?
User table already exists.
<createTable tableName="user">
<column name="user" type="varchar(255)">
<constraint nullable="false">
</column>
<column name="user_id" type="varchar(255)"/>
<column name="password" type="varchar(255)"/>
<column name="email" type="varchar(255)"/>
</createTable>
<addPrimaryKey tableName="user"> columnNames="user" constraintName="user_pk">
Duplicate user occurred in userTable.
The pk was removed because the user could have a duplicate name.
However, since we need to have the value of #Id, if we add the ID and set the autoIncrement, there will be a problem.
<dropPrimaryKey tableName="user"/>
<addColumn tableName="user">
<column name="id" type="BIGINT"/>
</addColumn>
<createSequence
incrementBy="1"
maxValue="9223372036854775807"
minValue="1"
startValue="1"
sequenceName="user_sequence"/>
Error Message
Reason: liquibase.exception.DatabaseException: ERROR: column "id" of relation "user" contains null values [Failed SQL: (0) ALTER TABLE "public"."user" ADD CONSTRAINT "PK_user" PRIMARY KEY ("id")]
Please check this SO post.
<changeSet id="1" author="Me">
<dropPrimaryKey tableName="tv_campaigns"/>
<addColumn tableName="tv_campaigns">
<column name="ID" type="bigint(20)" autoIncrement="true">
<constraints nullable="false" primaryKey="true" unique="true"/>
</column>
</addColumn>
<addAutoIncrement tableName="tv_campaigns" columnName="ID" columnDataType="bigint(20)"/>
</changeSet>
Try using the addAutoIncrement tag, read more about it here.

Liquibase - change on delete type of foreign key for a table

Is it possible to change the foreign key on delete method from NO ACTION to SET NULL in liquibase?
Yes, it's possible. There's onDelete attribute in <addForeignKeyConstraint> which you can set to:
CASCADE
SET NULL
SET DEFAULT
RESTRICT
NO ACTION
If you already have a foreign key, then you can drop existing constraint and recreate it with the settings you need.
<changeSet id="changeset-id" author="changeset-author">
<preConditions onFail="MARK_RAN">
<foreignKeyConstraintExists foreignKeyName="fk_foo_bar"/>
</preConditions>
<dropForeignKeyConstraint baseTableName="table_foo" constraintName="fk_foo_bar"/>
<addForeignKeyConstraint baseTableName="table_foo" baseColumnNames="foo_col"
constraintName="fk_foo_bar"
referencedTableName="table_bar" referencedColumnNames="bar_col"
onDelete="SET NULL"/>
</changeSet>

Check constraint on table in liquibase

I want to create a check constraint on a table using liquibase, this is the check constaint :
alter table userprefs add constraint chk_null CHECK (updatedate IS NOT NULL OR updateuser IS NOT NULL);
I googled about it but all I can find is how to create the check constraint on a column.
How this is can be done on liquibase ?
Liquibase does not support check constraints "natively". You need to put that into a <sql> tag:
<changeSet author="ichigo" id="1">
<sql>
alter table userprefs add constraint chk_null
CHECK (updatedate IS NOT NULL OR updateuser IS NOT NULL);
</sql>
</changeSet>

Check if the unique constraint exists and drop it using liquibase

I have a changeset wherein I initially check if the unique constraint exists and then if it does it will drop the constraint.
<changeSet author="loren"
id="DROP_UNIQUE_CONSTRAINT_RULEPRIORITY_ORACLE_v1" dbms="oracle">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="1">
SELECT COUNT(*)
FROM USER_CONSTRAINTS
WHERE CONSTRAINT_NAME='UC_RULES_PRIORITY'
</sqlCheck>
</preConditions>
<dropUniqueConstraint constraintName="UC_RULES_PRIORITY"
schemaName="${main.schema}"
tableName="RULES"/>
</changeSet>
The issue with this is it does not seem to pass the precondition. It always says MARK_RAN meaning there was no constraint found. In turn, the constraint will never be dropped.
I have tried executing the SELECT statement in my db and it returns 1.
Is this the correct way or is there an alternate solution for this?

Joining Tables with Composite Primary Keys in Hibernate hbm files

I have two table to be joined using hbm file.
The scenario is as follows
Table B has a composite PK.
Table B
a1 (pk)
a2 (pk)
a3 (pk)
foo
bar
========
Table A has a primary key and is a foreign key from Table B
Table A
a1 (pk,fk)
hip
hop
========
This a one to many relation from Table A to B.
Can any one help me out with the hbm file mapping?
I am jotting down wot i have tried.
For Table B
<class>
<composite-id name="XXXX" class=".....">
<key-property name="a1" column="a1" type="int"/>
<key-property name="a2" column="a2" type="int"/>
<key-property name="a3" column="a3" type="int"/>
</composite-id>
<property name="foo" column="foo" type="java.lang.Float"></property>
<property name="bar" column="bar" type="java.lang.Float"></property>
</class>
For Table A
Normal hibernate mapping.
How to join both tables?
a workaround could be afake propertyref to break out of the compositeId
<class class="B">
<property name="a1_again" column="a1" insert="false" update="false"/>
<bag name="As" class="A">
<key property-ref="a1_again"></key>
...
</bag>
</class>