Liquibase run part of a changeset? - sql

I have the below changeset but, I may want to add additional inserts in the future. It could be in the hundreds or thousands.
--changeset author:changesetid endDelimiter:;
INSERT INTO "MY_TABLE" (id, name) VALUES (1, 'bob');
INSERT INTO "MY_TABLE" (id, name) VALUES (2, 'jim');
INSERT INTO "MY_TABLE" (id, name) VALUES (3, 'mick');
I can't execute previous inserts because that would throw errors about that data already existing. Similarly, I don't want to have dozens or hundreds of individual changesets with their own combination of different inserts overtime. I would like everything consolidated under 1 changeset.
Maybe I could use some type of precondition with this attribute but, I wouldn't want to keep checking the table size (or have to update the precondition value) everytime I need to update the changeset.
--preconditions onFail:WARN

How about:
create 2 changesets
1st
-insert your data to e.g MY_TABLE_TMP ( table without PK allowing duplicates)
add TRUNCATE at the beginning of this changeset and new inserts below,
2st
your final changeset (sql script)
use a LOOP to get data from MY_TABLE_TMP and insert it with dynamic SQL into
MY_TABLE
when error occures, ignore it and continue a LOOP
Rafał

Does your target database support an UPSERT or MERGE statement? If so, you could make your SQL script so if the record is already found in the table nothing happens, and if not found the record is inserted. This would make your script more complicated, but should achieve what you are looking for if you set the changeset to runOnChange.

Related

How can I INSERT data into two tables simultaneously with only one sql script db2?

How would I insert into multiple tables with one sql script in db2
For example, insert a row into T1 DOCK_DOOR and then insert into T2 DOCK_DOOR_LANE multiple times based on the dock_door_sysid from the first table.
My first approach was the following. I was attempting to use a with with three inserts. on the other hand, doing to inserts on the second table is not and option if this can be automated with one insert.
thanks for any feedback
sql example
WITH ins AS (
INSERT INTO DBF1.DOCK_DOOR (DOCK_DOOR_SYSID,DOOR_NUMBER,DOOR_NAME,DOCK_SYSID,DOOR_SEQ,ENCRYPTION_CODE,RFID_ENBLD_FLAG,LANES_COUNT,CMNT_TEXT,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER,ACTIVE_FLAG,STATUS_SYSID,DOOR_TYPE_SYSID)
VALUES (nextval for DBF1.DOCK_DOOR_SEQ,'026','DOOR025',61,25,NULL,'N','2',NULL,current timestamp,'SQL_INSERT',current timestamp,'SQL_INSERT',0,NULL,1723,1142)
RETURNING door_number,dock_door_sysid),
ins2 AS (
INSERT INTO SIT.DOCK_DOOR_lane (DOCK_DOOR_LANE_SYSID,DOOR_LANE_ID,DOCK_DOOR_SYSID,LANE_ID,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER)
VALUES (nextval for DBF1.DOCK_DOOR_LANE_seq,door_number||''||'A',dock_door_sysid,'A',current timestamp},'SQL_INSERT',current timestamp,'SQL_INSERT',0)
SELECT door_number,dock_door_sysid FROM DBF1.DOCK_DOOR
RETURNING door_number,dock_door_sysid)
INSERT INTO DBF1.DOCK_DOOR_lane (DOCK_DOOR_LANE_SYSID,DOOR_LANE_ID,DOCK_DOOR_SYSID,LANE_ID,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER)
VALUES (nextval for DBF1.DOCK_DOOR_LANE_seq,door_number||''||'B',dock_door_sysid,'B',current timestamp},'SQL_INSERT',current timestamp,'SQL_INSERT',0)
SELECT door_number,dock_door_sysid FROM DBF1.DOCK_DOOR;
Table 1 = dock_door
Table 2 = Dock_door_lane
You could do it with a trigger on the dock_door table.
However, if you're on a recent, version on IBM i. You might be able to make use of data change table reference
Your statement would look something like this
insert into dock_door_lane
select <....>
from final table (insert into dock_door <...>)
I'm not sure it will work, as this article indicates that at least at a couple of years ago DB2 for i didn't support the secondary insert required.
This old SO question also seems to confirm that at least at v7.1, the double insert isn't supported.
If I get a chance, I'll run a test on a 7.2 system Monday.

How to insert into the table a user name record

I've a table. In this table I have two columns - 'insert_name' and 'modified_name'. I need to insert into this columns data about who has inserted data into the table('insert_name') and who has changed these data in the table (modified_name). How it can be done?
You are looking for basic DML statements.
If your record is already in the table, then you need to UPDATE it. Otherwise, when you are about to add your record to it and it doesn't already exist in the destination table then you are looking for INSERT INTO statement.
Example of updating information for record with first id:
UPDATE yourtable SET insert_name = 'value1', modified_name = 'value2' WHERE id = 1
Example of inserting new record:
INSERT INTO yourtable(id, company_name, product_name, insert_name)
VALUES (1, 'Google', 'PC', 'value1')
If you are looking for automatic changes to those columns then you need to look into triggers.
Remember that more often than not you may find that the application connecting to the database is using single database user in which case you probably know the context within the application itself (who inserts, who updates). This does eliminate triggers and put the task straight on simple insert/update commands from within your application layer.
You might be able to use the CURRENT_USER function to find the name of the user making the change.
The value from this function could then be used to update the appropriate column. This update could be done as part of the INSERT or UPDATE statement. Alternatively use an INSERT or UPDATE trigger.
Personally I avoid triggers if I can.
For those 2 columns add Current_User as Default constraint.
As the first time Insert Statement will save them with current login user names. For update write an Update trigger with the same Current_User statement for the column Modified_Name.
If and only if your application business logic can't update the column modified_nme then only go for Trigger.
See the use of Current_Use
https://msdn.microsoft.com/en-us/library/ms176050.aspx

SQL Server Triggers on Specific Data

Afternoon all!
I'm working on a large database at work, and they've specifically asked me to implement triggers into the database.
Basically, we have a set of tables all containing different information, but if, in one particular table, a certain range of values are entered into the 'fieldID' column, I need it to trigger.
In this case, if a user INSERT data, with the fieldID >= 4 AND fieldID <=9, I need the SQL Server to trigger, with a command of inserting the data to a different table.
For example,
INSERT INTO myTestTable(state, process, fieldID) VALUES ('ACTIVE', 13,9);
(and the database actually performing)
INSERT INTO myFieldTable(state, process, fieldID) VALUES ('ACTIVE', 13,9);
INSERT INTO myTestTable(state, process, fieldID) VALUES ('ACTIVE', 13,42);
(and the database actually performing)
INSERT INTO myTestTable(state, process, fieldID) VALUES ('ACTIVE', 13,42);
I've found loads of stuff online about triggers and how they work in when a new record is entered in general, but nothing for specific data
In the simplest form, you can write a INSTEAD OF INSERT trigger to achieve what you are trying. something like below
CREATE TRIGGER trg_testoninsert on myTestTable
INSTEAD OF INSERT
AS
BEGIN
IF inserted.fieldID >= 4 AND inserted.fieldID <=9
INSERT INTO myFieldTable(state, process, fieldID)
select state, process, fieldID
from inserted;
END;
GO

Getting INSERT errors when I do UPDATE?

At work we have a SQL Server database. I don't know the db that well. I have created a new column in the table for some new functionality....straight away I have started seeing errors
My statement was this:
ALTER TABLE users
ADD locked varchar(50) NULL
GO
The error is:
Insert Error: Column name or number of supplied values does not match table definition
I have read that the error message appears when during an INSERT operation either the number of supplied column names or the number of supplied values does not match the table definition.
But I have checked so many times and i have changed the PHP code to include this columns data yet I still receive the error.
I have run the SQL query directly on the db and still get the error.
Funny enough the query which gets the error is an Update.
UPDATE "users"
SET "users"."date_last_login" = GETDATE()
WHERE id = 1
Have you considered it could be a trigger causing it? 
This is the error message you would get.
If its an Update action causing it check trigger actions that Updates on that table run.
Do it with:
#sp_helptrigger Users, 'UPDATE';
This will show triggers occuring with ‘update’ actions.
If there is a trigger, grab the triggers name and run the below (but replace TriggerNameHere with real trigger):
#sp_helptext TriggerNameHere;
This will give you any SQL that the trigger runs and could be the INSERT the error message is referring to.
Hope this helps
Aside from TRIGGERS,
the reason for that is because you are using implicit type of INSERT statement. Let's say your previous number of columns on the table is 3. You have this syntax of INSERT statement,
INSERT INTO tableName VALUES ('val1','val2','val3')
which executes normally fine. But then you have altered the table to add another column. All of your INSERT queries are inserting only three values on the table which doesn't matches to the total number of columns.
In order to fix the problem, you have to update all INSERT statements to insert 4 values on the table,
INSERT INTO tableName VALUES ('val1','val2','val3', 'val4')
and it will normally work fine.
I'll advise you to use the EXPLICIT type of INSERT wherein you have to specify the columns you want to insert values with. Eg,
INSERT INTO tableName (col1, col2, col3) VALUES ('val1','val2','val3')
in this ways, even if you have altered your tables by adding additional columns, your INSERT statement won't be affected unless the column doesn't have a default value and which is non-nullable.

insert data in multiple tables

hi i have a problem to insert data in multiple tables. i have define primary key & reference key in tables now i want to insert data in both tables in single query.......how can i do this...........???????
Your question isn't exactly clear on what the particular problem is. I can see three possibilities:
1. You want to insert into two tables wiht a single INSERT statement
2. You want to do two inserts, but without anything else being able to 'get in the middle'
3. You want to insert into one table, then get the primary key to insert into the second table
The answer to 1. is simple:
You can't.
The answer to 2. is simple too:
BEGIN TRANSACTION
INSERT INTO <table1> (a,b,c) VALUES (1,2,3)
INSERT INTO <table2> (a,b,c) VALUES (1,2,3)
COMMIT TRANSACTION
The answer to 3. is has several possibilities. Each depending on exactly what you want to do. Most likely you want to use SCOPE_IDENTITY() but you may also want to look up ##identity and IDENT_CURRENT() to understand the various different options and complexities.
BEGIN TRANSACTION
INSERT INTO <dimension_table> (name)
VALUES ('my new item')
INSERT INTO <fact_table> (item_id, iteam_value)
VALUES (SCOPE_IDENTITY(), 1)
COMMIT TRANSACTION
This is what transactions are meant for. Standard SQL does not permit a single statement inserting into multiple tables at once. The correct way to do it is:
-- begin transaction
insert into table 1 ...
insert into table 2 ...
commit
Does your language support the INSERT ALL construct? If so, that is the best way to do this. In fact it's the only way. I posted an example of this construct in another SO thread (that example syntax comes from Oracle SQL).
The other option is to build a transactional stored procedure which inserts a record into the primary key table followed by a record into the referencing table.
And 1 of your choice to do that is use ORM (like Hibernate, NHibernate) the you make your object and set other relation to it and finally just save the main object , like:
A a;
B b;
C c;
a.set(b);
a.set(c);
DAO.saveOrUpdate(a);
you must notice your DAO.saveOrUpdate(a); line of code just work with hibernate but it insert data into 3 table A, B, C.