Liquibase: Keep changes from script but remove the changelog in changelog table - liquibase

I am using liquibase for applying database changes. I have below changeset and below are the entries in changelog:
Changeset:
<changeSet author="me" id="1">
<addColumn tableName="order">
<column name="isBlocked" type="boolean">
</addColumn>
</changeSet>
<changeSet author="me" id="2">
<addColumn tableName="order">
<column name="shouldDecline" type="boolean">
</addColumn>
</changeSet>
In DB :
Changelog table:
-------------------------
ID | AUTHOR | AND SO ON |
-------------------------
1 | me | AND SO ON |
2 | me | AND SO ON |
-------------------------
Order Table:
--------------------------------------------
ID | isBlocked | shouldDecline | AND SO ON |
--------------------------------------------
1 | true | false | AND SO ON |
2 | true | false | AND SO ON |
--------------------------------------------
Now I want to keep the changes in Order table, but I want to remove ID#2 from changelog table. So basically I want to keep the changes from the changeSet but I want to delete the entry in changeSet and maintain only ID#1 in change but Order table should have shouldDecline column. Anyway to achieve this?
from documentation there is rollback but it wil also revert the changes from the script which I dont want. Any suggestions on this?

Feel free to remove unnecessary rows from databasechangelog table with a delete SQL statement using change id.
As a result, the DDL stays applied to the database, but the log record of it is deleted.
But you should know, that changelog it's a main feature of liquibase, and if you need to remove records from the changelog, maybe you don't need liquibase at all.
Manually editing the changelog it's convenient for the dev and test environment, but it is strictly not recommended in production.

There is no way to remove a changeset from the databasechangelog table without removing the actual change from the database.
I would question why you want to do this.

Related

Impala ACID table select ERROR: Operation not supported on transactional (ACID) table:

I'm using impala 3.4 directly with hive 3.1.
The problem is that if you create a general table in the hive and then select it in impala, an error occurs.
The error message is as follows:
Query: show tables
+----------+
| name |
+----------+
| customer |
| lineitem |
| nation |
| orders |
| part |
| partsupp |
| region |
| supplier |
| t |
+----------+
Fetched 9 row(s) in 0.02s
[host.cluster.com] default> select * from customer;
Query: select * from customer
Query submitted at: 2020-11-20 09:56:12 (Coordinator: http://host.cluster.com:25000)
ERROR: AnalysisException: Operation not supported on transactional (ACID) table: default.customer
In the hive, the acid table and the orc table are only concerned with whether to delete or update, but I knew that selection is common.
In fact, the select statement is normally executed through hive jdbc. Only impala would like to help you understand why this error occurs.
I solved this problem. It was confirmed that the table created through Hive in impala operates normally.
There are two possible causes:
Connect impala built with Hive2 to Hive 3 databases.
When creating a Hive Table that I did not recognize, set the default flag related to ACID.
This version can't read ACID table wich are created by Hive. Hive creates ACID table by default.

Use SSIS to split a single field value into multiple rows in a second table

So the situation is I am writing an SSIS package to migrate data from an old database to a new database. In the old database we have a Text column called comments that is filled with sometimes 30MB of text. Most of these are comment threads that have time stamps. I would like to use the timestamps by using a regex or some such thing to split the data up and move it to a second child table called comments. It then needs to reference the PK of the original record as well. Thanks!
So
Table1 [Profile]
PK | Comments
1 | '<timestamp> blah <timestamp> blah blah'
will turn into
Table1 [Profile]
PK | Comments
1 | ''
Table2 [Comments]
PK | FK | Comment
1 | 1 | '<timestamp> blah'
2 | 1 | '<timestamp> blah blah'
As wp78de suggested I resolved this by creating a script task and modified the output as it copies.

Adding composite unique constraint in Liquibase

I'm creating a link table which has 3 columns; id, product_id, tournament_id.
Adding a uniqueConstraint to the "id" column is trivial, but I want to ensure that any pair of (product_id, tournament_id) is unique.
The example at Liquibase.org shows
<changeSet author="liquibase-docs" id="addUniqueConstraint-example">
<addUniqueConstraint catalogName="cat"
columnNames="id, name"
constraintName="const_name"
deferrable="true"
disabled="true"
initiallyDeferred="true"
schemaName="public"
tableName="person"
tablespace="A String"/>
</changeSet>
but is it possible to accomplish this within a <createTable> block?
Also, just to confirm; does this create a composite unique constraint on the two columns, or does it create two separate unique constraints?
You can read liquibase manual also similar problem you can find here
In your case it should be:
<changeSet author="liquibase-docs" id="addUniqueConstraint-example">
<addUniqueConstraint
columnNames="product_id, tournament_id"
constraintName="your_constraint_name"
tableName="person"
/>
</changeSet>
I am pretty certain that:
You can't do it inside the createTable tag itself, but you can do it within the same changeset as when the table is created.
It does create a composite unique constraint on the two columns. One way you can check is to run liquibase with the command to generate the SQL for update rather than running the update command and check what it does for your database. On the command line, rather than running liquibase update you would run liquibase updateSQL.
In case people like myself are still asking themselves this question years later: (by now) it is possible to do this within the createTable tag itself if you provide the same name for the constraint:
<changeSet id="composite-unique-example" author="composite-unique-example">
<createTable tableName="example">
<column name="foo" type="bigint">
<constraints unique="true" uniqueConstraintName="foo-bar_unique"/>
</column>
<column name="bar" type="bigint">
<constraints unique="true" uniqueConstraintName="foo-bar_unique"/>
</column>
</createTable>
</changeSet>
Running Liquibase 4.5.0 and MySQL 5.7:
mysql> insert into example (foo, bar) values (1, 2), (2, 1), (1, 3);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from example;
+------+------+
| foo | bar |
+------+------+
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
+------+------+
3 rows in set (0.00 sec)
mysql> insert into example (foo, bar) values (1, 2);
ERROR 1062 (23000): Duplicate entry '1-2' for key 'foo-bar_unique'

Triggering mysql delete in another table?

I have 3 tables in my database:
| systems |
|-------------|
| system_id |
|-------------|
| systems_maintenances |
|-------------------------|
| systems_maintenances_id|
| system_id |
| maintenance_id |
|-------------------------|
| maintenances |
|-------------------------|
| maintenance_id |
|-------------------------|
I'd like that when I delete a system, the maintenance being deleted too.
For the moment it only deletes in the systems_maintenances table.
I think a trigger is the best (and only?) way to do that.
I created this one:
CREATE TRIGGER `deleteMaintenance` BEFORE DELETE ON `systems`
FOR EACH ROW BEGIN
DELETE FROM maintenances
WHERE maintenance_id = systems_maintenances.maintenance_id;
END
The problem is I get the error:
DELETE FROM SNMProject.systems WHERE systems.system_id =16
MySQL a répondu:
#1054 - Unknown column 'systems_maintenances.maintenance_id' in 'where clause
How to solve my problem?
I don't know if it can help but I have this too for the systems_maintenances table:
(source: xooimage.com)
In a trigger, you don't refer to the table name of the table being affected. Instead, you refer to a proxie for it. That proxie depends on the database. In MySQL, it is new and old.
I suspect that you want something like this:
CREATE TRIGGER `deleteMaintenance` BEFORE DELETE ON `systems` FOR EACH ROW BEGIN
DELETE FROM maintenances m
WHERE maintenance_id IN (SELECT maintenance_id
FROM systems_maintenances sm
WHERE systems_maintenances.system_id = old.system_id
)
END;
There are other ways to express this logic, but this gives a good idea of the structure.
You can do essentially the same thing using cascading deletes, if you prefer. That way, you don't have to write triggers and can put the logic in the create table statement.

MySQL data version control

Is there any way to setup MySQL to every time a row is changed, then a row to another table/database is created with what the data was originally? (with time stamping)
If so how would I go about doing it?
E.g.
UPDATE `live_db`.`people`
SET `live_db`.`people`.`name` = 'bob'
WHERE `id` = 1;
Causes this to happen before the update:
INSERT INTO `changes_db`.`people`
SELECT *
FROM `live_db`.`people`
WHERE `live_db`.`people`.`id` = 1;
And if you did it again it would result in something like this:
`live_db`.`people`
+----+-------+---------------------+
| id | name | created |
+----+-------+---------------------+
| 1 | jones | 10:32:20 12/06/2010 |
+----+-------+---------------------+
`changes_db`.`people`
+----+-------+---------------------+
| id | name | updated |
+----+-------+---------------------+
| 1 | billy | 12:11:25 13/06/2010 |
| 1 | bob | 03:01:54 14/06/2010 |
+----+-------+---------------------+
The live DB needs to have a created time stamp on the rows, and the changes DB needs to have a time stamp of when the live DB row was updated.
The changes DB will also have no primary keys and foreign key constraints.
I'm using InnoDB and MySQL 5.1.49 but can upgrade if required.
Use a Trigger
MySQL support for triggers started with MySQL version 5.0.2.
You can create a trigger:
DELIMITER \\
CREATE TRIGGER logtrigger BEFORE UPDATE ON live_db.people
FOR EACH ROW BEGIN
INSERT INTO changes_db.people(id,name,updated) VALUES(OLD.id,OLD.name,now());
END;
\\
This is how I ended up doing it
DELIMITER |
# Create the log table
CREATE TABLE IF NOT EXISTS `DB_LOG`.`TABLE`
LIKE `DB`.`TABLE`|
# Remove any auto increment
ALTER TABLE `DB_LOG`.`TABLE` CHANGE `DB_LOG`.`TABLE`.`PK` `DB_LOG`.`TABLE`.`PK` INT UNSIGNED NOT NULL|
# Drop the primary keys
ALTER TABLE `DB_LOG`.`TABLE` DROP PRIMARY KEY|
#Create the trigger
DROP TRIGGER IF EXISTS `DB`.`update_TABLE`|
CREATE TRIGGER `DB`.`update_TABLE` BEFORE UPDATE ON `DB`.`TABLE` FOR EACH ROW
BEGIN
INSERT INTO `DB_LOG`.`TABLE`
SELECT `DB`.`TABLE`.*
FROM `DB`.`TABLE`
WHERE `DB`.`TABLE`.`PK` = NEW.`PK`;
END|
DELIMITER ;
Sorry to comment on an old post, but I was looking to solve this exact problem! Thought I would share this information.
This outlines a solution perfectly:
http://www.hirmet.com/mysql-versioning-records-of-tables-using-triggers