Update statement in JdbcBatchItemWriter - sql

I am not able to update the database table correctly using JdbcBatchItemWriter. Below is the code fragment. insert on an empty table is getting correct response but update is not happening on input table.
<bean id="odbWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource"></property>
<property name="sql">
<value>
<![CDATA[
update employeethree set salary = :salary, designation = :designation, promotioneligibility = :promotionEligibility
]]>
</value>
</property>
<property name="itemSqlParameterSourceProvider">
<bean
class="batchjobreaddb.CustomBeanPropertyItemSqlParameterSourceProvider" />
</property>
If i change the query inside CDATA to :
insert into employeetwo values(:empId, :empName, :dept , :salary, :designation, :experienceInMonths, :promotionEligibility)
then it's getting me the desired results. (EmployeeTwo has same structure but is empty.)
Please help. Thanks :)

Your UPDATE query has no WHERE clause. How are you to know which record to update?
For proper update behavior, you must specify a WHERE clause that properly identifies the record(s) you wish to modify with the UPDATE query.
This is obviously not necessary with an INSERT query, because you are creating a brand new record and not modifying an existing one.
Assuming from your example INSERT query that the employee id field is empid, try modifying your JdbcBatchItemWriter to set the sql value to:
<property name="sql">
<value>
<![CDATA[
UPDATE employeethree
SET salary = :salary,
designation = :designation,
promotioneligibility = :promotionEligibility
WHERE empid = :empId
]]>
</value>
</property>

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>

LiquiBase changeset: how do build a where clause based on ANOTHER table's column

Building upon the question How to build a WHERE-clause in a LiquiBase changeset, I would like to choose the default value of a column based on the value of a column from a different table.
For instance, I have two tables, order and order_history. Pls note that we maintain all our orders in both order in order_history as well. Once an order is completed, it is removed from order table.
order has a column 'status' but we missed it on order_history, you can call it a bad design.
How do I add 'status' to order_history now, and copy the value from the corresponding order
in order table for existing data at the time of upgrade? Is there a way to do this in liquibase?
If order and order_history are connected with the foreign key, then you can just do the following:
<changeSet id="foo" author="bar">
<preConditions onFail="MARK_RAN">
<and>
<columnExists tableName="order" columnName="status"/>
<columnExists tableName="order_history" columnName="status"/>
</and>
</preConditions>
<comment>Update order_history.status with values from order.status, where order.id = order_history.order_id</comment>
<update tableName="order_history">
<column name="status" valueComputed="SELECT o.status FROM order o WHERE o.id = order_id"/>
</update>
</changeSet>
If these tables are not connected, then you may use defaultValueComputed when you're adding a new column:
<addColumn tableName="order_history">
<column name="status" type="varchar(255)" defaultValueComputed="some SQL query here"/>
</addColumn>

Search for a particular column name from with a XML column in SQL Server

Just wanted to get some help here. I have a situation where I need to find some data from within the <Column Name> tag as shown in the XML below.
I had a issue where some badly formatted data was exported in the system, I found that piece but now there is a process where I IMPORT data out of the system. Now I have a table which contains XML stored.
I have to iterate through the whole table to see if that column name exists in that particular ID column and if it does I will return the ID. Say for example my table name is Sample and the columns are (ID, ImportXML).
Any help on how I can achieve this ? New to dealing with XML from within SQL Server.
<?xml version="1.0" encoding="UTF-8"?>
<ExportConfiguration id="SampleExport">
<definitions>
<ClientName Value="Sample"/>
<FileType Value="XML"/>
<FileName>
<Value Value="SomeValue"/>
</FileName>
<Columns>
<Column Name="abc" DataType="String" Value="test123"/>
<Column Name="findthis" DataType="String" Value="Test456"/>
</Columns>
</definitions>
</ExportConfiguration>
So basically from the above mentioned code I want to get the value from within <Columns>/<Column Name> = "findthis" so basically findthis is my keyword and I want to get all the ID's of the columns which contain the keyword findthis just for argument sake.
Something like this:
-- Test table.
declare #xTable table (ID int identity(1,1) primary key clustered, XMLData xml)
-- Insert an XML document. I only did one, but the same would work for multiple
insert into #xTable
select '<?xml version="1.0" encoding="UTF-8"?>
<ExportConfiguration id="SampleExport">
<definitions>
<ClientName Value="Sample"/>
<FileType Value="XML"/>
<FileName>
<Value Value="SomeValue"/>
</FileName>
<Columns>
<Column Name="abc" DataType="String" Value="test123"/>
<Column Name="findthis" DataType="String" Value="Test456"/>
</Columns>
</definitions>
</ExportConfiguration>'
-- Return everything from the table with your XML where there is an attribute at the path "/ExportConfiguration/definitions/Columns/Column" with the name "Name" and the value "findthis"
select *
from #xTable
where XMLData.exist('/ExportConfiguration/definitions/Columns/Column[#Name eq "findthis"]') = 1

Liquibase Insert computed value with multiple ids

I am trying to insert values into a database. I think the SQL would look like this:
INSERT INTO `tb_config` (`name`, `value`, `description`, `unity_id`)
(SELECT 'new_rule', true, 'rule description', id FROM tb_unity );
However, I want to do it with Liquibase, using a changeset:
<changeSet author="Luis Sukys" id="1022" >
<insert tableName="tb_config">
<column name="name">new_rule</column>
<column name="value">false</column>
<column name="descricao">rule description</column>
<column name="unidade_id" valueComputed="SELECT id FROM tb_unity" />
</insert>
</changeSet>
I've seen the use of valueComputed but with a where clause.
The idea is that it includes one row in tb_config for each id in tb_unity.
I am actually getting a 'ValidationFailedException' from liquibase.
Any help?
I use Navicat with MySQL and when I run this code, it includes one new row int tb_config for each row in tb_unity. The field i use from tb_unity is 'id'.
If I have 05 unities in tb_unity, it must add 05 rows in tb_config, with same values, only change the unity's id.
If you try running that SQL using whatever SQL tool you use, you will see that the problem is that you do indeed need a where clause. Which row of tb_unity do you want to use the id from?

Nhibernate Filter in a Join table

I'll try to filter to have a one to one join in subclasses,
I set the filter condition in key column field, in a simple query it works, in more complicated it does not resolve alias.
is there a trick for setting the alias in the second column??
<join table="Aview" inverse="true">
**<key column="ID_A and ID_C=:MyFilter.IdCC" />**
<property name="IdBlabla" insert ="false" update ="false" column="ID_BlaBla"/>
<property name="Tipo" insert ="false" update ="false" />
<many-to-one name="CC" column="ID_C" cascade="none" insert ="false" update ="false"/>
</join>