Update Single XML Node Value of XML Column using SQL Server - sql

I want to update single value of XML Node in SQl Server
Below is the table structure
XML Structure
<PayDetails>
<Column Name="FG" DataType="float" Value="7241" />
<Column Name="SKILL" DataType="float" Value="3" />
<Column Name="PI" DataType="float" Value="87" />
<Column Name="MD" DataType="float" Value="30" />
<Column Name="LD" DataType="float" Value="4" />
<Column Name="WEEKOFF_DAYS" DataType="float" Value="4" />
<Column Name="NETPAY" DataType="float" Value="5389" />
</PayDetails>
I want to update value of FG from 7241 to 8000

You want to use replace value of...with keywords:
Try something like the following:
update tablename
set TransactionFieldDetails.modify(
'replace value of
(/PayDetails/Column[#Name="FG"]/#Value)[1]
with "8000"');

Related

Sql server xpath conditionnal query

I have a table where one field called 'configuration' is type of XML:
<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>
What I would like to do, is to retrieve all the table records or at least count the table records that have a field 'configuration' containing at least one 'element' attribute containing a 'value' attribute equals to 'lisa'.
What I have for the moment, is a query that can retrieve the 'value' attribute of the specified 'element' position, for example:
select Configuration.value('(/configuration/element/#value)[0]', 'nvarchar(max)') // returns me 'john'
select Configuration.value('(/configuration/element/#value)[1]', 'nvarchar(max)') // returns me 'kevin'
This is a bit of pseudo-SQL in the absence of a dataset, and a bit of guesswork; in that I (think) you simply want to return the rows(?) where there is a the node configuration/element has the value property 'lisa'. IF my guess is right, then something like this will work (you'll ened to replace object names in Braces({}):
SELECT {Columns}
FROM [{Your Table}] YT
WHERE EXISTS (SELECT 1
FROM [{Your Table}] E
CROSS APPLY E.[{Your XML Column}].nodes('configuration/element') C(E)
WHERE E.[{Your ID Column}] = YT.[{Your ID Column}]
AND C.E.value('./#value','varchar(50)') = 'lisa');
Example:
WITH VTE AS(
SELECT 1 AS ID,
CONVERT(xml,'<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>') AS XMlCol
UNION ALL
SELECT 2 AS ID,
CONVERT(xml,'<configuration>
<element value="craig" />
<element value="donald" />
<element value="jenny" />
<element value="jayne" />
</configuration>') AS XMlCol)
SELECT *
FROM VTE YT
WHERE EXISTS (SELECT 1
FROM VTE E
CROSS APPLY E.XMlCol.nodes('configuration/element') C(E)
WHERE E.ID = YT.ID
AND C.E.value('./#value','varchar(50)') = 'lisa');
This only returns the row with an ID of 1.
Please try the below,
declare #xml as xml
set #xml='<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>'
SELECT T.c.value('./#value','nvarchar(250)' ) As element
FROM #xml.nodes('//element') AS T(c)

Stripping data from xml in SQL Server

One of my tables with xml datatype has the following xml information:
<RequestMetaData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MetaData Type="DocImport">
<Keywords>
<Key Name="Zone" Value="MIO" />
<Key Name="ClassificationStrategy" Value="NeedClassification" />
<Key Name="Folder" Value="0456e6ca" />
</Keywords>
</MetaData>
<MetaData Type="SourceResponse">
<Keywords>
<Key Name="NotificationResponse_20180427-150426" Value="Received successful response from Source" />
</Keywords>
</MetaData>
</RequestMetaData>
I need to write an SQL query to fetch the value of Classification strategy based on key name.
I have added the xml in a variable #xml and used the following code. It is returning NULL.
select A.b.value('ClassificationStrategy[1]', 'VARCHAR(30)') AS CS
FROM #xml.nodes('/RequestMetaData/MetaData/Keywords') AS A(b)
Can someone please help me with this.
You can read your XML in various ways. Use a simple .value() with an XPath/XQuery expression to retrieve a single value, use .query to retrieve a part of the XML or use .nodes() to return repeated elements as derived table:
DECLARE #xml XML=
N'<RequestMetaData xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MetaData Type="DocImport">
<Keywords>
<Key Name="Zone" Value="MIO" />
<Key Name="ClassificationStrategy" Value="NeedClassification" />
<Key Name="Folder" Value="0456e6ca" />
</Keywords>
</MetaData>
<MetaData Type="SourceResponse">
<Keywords>
<Key Name="NotificationResponse_20180427-150426" Value="Received successful response from Source" />
</Keywords>
</MetaData>
</RequestMetaData>';
--Read the whole lot
SELECT md.value('#Type','nvarchar(max)') AS MetaDataType
,k.value('#Name','nvarchar(max)') AS KeyName
,k.value('#Value','nvarchar(max)') AS KeyValue
FROM #xml.nodes('/RequestMetaData/MetaData') A(md)
OUTER APPLY md.nodes('Keywords/Key') B(k);
--Get one key's value by name (anywhere in the doc)
DECLARE #keyName VARCHAR(100)='ClassificationStrategy';
SELECT #xml.value('(//Key[#Name=sql:variable("#keyName")]/#Value)[1]','nvarchar(max)');
--Use the meta data type as additional filter (if key names are not unique per doc)
DECLARE #kName VARCHAR(100)='ClassificationStrategy';
DECLARE #mdType VARCHAR(100)='DocImport';
SELECT #xml.value('(/RequestMetaData
/MetaData[#Type=sql:variable("#mdType")]
/Keywords
/Key[#Name=sql:variable("#kName")]
/#Value)[1]','nvarchar(max)');

Loading data from a CSV file using <loadUpdateData> Postgres

I would appreciate some suggestions. I am accomplishing a simple load of one table with five records from a CSV file. When I load the table, I get the below the error:
liquibase.exception.DatabaseException: org.postgresql.util.PSQLException: ERROR: zero-length delimited identifier at or near """"
This is by csv file
1,Nate Happy,natehappy1761#me.com,1761 Brookview Trail,(205) 555-1212
2,Brigette Happy,brigettehappy7507#me.com,7507 Meadowgate Lane,(704) 555-1212
3,Katie Happy,katiehappy7507#me.com,7507 Meadowgate Lane,(704) 555-1212
4,Lauren Happy,laurenhappy#me.com,7507 Meadowgate Lane,(704) 555-1212
5,Jackson Hope,jacksonhope#me.com,7507 Meadowgate Lane,(704) 555-1212
This is my changeset for loading the data
<changeSet id="6-loadData" author="liquibase" dbms="postgresql" >
<preConditions onErrorMessage="Failed Pre Conditions for table" onFail="HALT">
<and>
<tableExists schemaName="public" tableName="contact" />
<sqlCheck expectedResult ="1">SELECT COUNT(*) contact</sqlCheck>
</and>
</preConditions>
<comment>Adding Data...</comment>
<loadUpdateData catalogName="pg_catalog"
encoding="UTF-8"
file="src/main/resources/data/contacts.csv"
primaryKey="contact_id"
quotchar="A String"
schemaName="public"
separator=","
tableName="contact">
<column name="contact_id" type="int" />
<column name="contact_name" type="varchar(45)"/>
<column name="email" type="varchar(45)" />
<column name="address" type="varchar(45)" />
<column name="telephone" type="varchar(45)" />
</loadUpdateData>
This is my changeset for creating the table:
<changeSet id="4 Create Table" author="liquibase" runAlways="true">
<preConditions onErrorMessage="Failed Pre Conditions for table" onFail="MARK_RAN">
<not><tableExists schemaName="public" tableName="contact"/> </not>
</preConditions>
<comment>Creating Table named: Contact...</comment>
<createTable tableName="contact" schemaName="public">
<column name="contact_id" type="int" >
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="contact_name" type="varchar(45)">
<constraints nullable="false"/>
</column>
<column name="email" type="varchar(45)">
<constraints nullable="false"/>
</column>
<column name="address" type="varchar(45)">
<constraints nullable="false"/>
</column>
<column name="telephone" type="varchar(45)">
<constraints nullable="false"/>
</column>
</createTable>
Here is the sequence I am using to the primary key (contact_id)
<changeSet id="2-Create Sequence" author="liquibase" runAlways="true">
<preConditions onErrorMessage="Failed Pre Conditions for sequence" onFail="MARK_RAN">
<not><sequenceExists schemaName="public" sequenceName="contactid_seq" /></not>
</preConditions>
<comment>Creating Sequence...</comment>
<createSequence sequenceName="contactid_seq"
incrementBy="1"
minValue="1"
maxValue="9223372036854775807"
startValue="1"
ordered="1"
schemaName="public"/>
This is how I am using the constraint:
<changeSet id="5-Add Constraint" author="liquibase">
<comment>Adding contactid_seq sequence to Contact table...</comment>
<addDefaultValue catalogName="pg_catalog"
columnDataType="int"
columnName="contact_id"
tableName="contact"
schemaName="public"
defaultValueSequenceNext="contactid_seq" />
Thanks for taking the time to read my post.
Russ
I discovered the CSV file was missing the HEADER column names. The LoadUpdateData's column elements use specific Java types, such as String instead of VARCHAR(45) and NUMERIC instead of "int". Once I corrected these two errors, I was successful.
Don't forget to change a string of quotchar, if you set it like in manual,
quotchar="A String"
then Liquibase will mark letter "A" as quotes.
You can exclude it from changeset and use default html quotes charset

performance is slow while running a DB query using Struts

I am using Struts to build a web application. Application server is Tomcat Server 6, database is Oracle 11G. I am executing an action class which contains the following DB query:
SELECT BV_USER__TEMP.CEC_ID AS USER_ID,
BV_USER_BEHRCHY_TEMP.LEVEL_NUM AS LEVEL_NUM,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME AS IAM__HIER_NAME,
'Total Development' AS TOTAL_ENGINEERING,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
INNER JOIN BV_SUB_BUSINESS_ENTITY BSE
ON (BV_USER_BE_HRCHY_TEMP.SUB_BUSINESS_ENTITY_DESCR =
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME)
WHERE IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND IAM_LEVEL_NUM=2
AND USER_ID=?
GROUP BY 1,2,3,4,5,6
UNION ALL
SELECT CEC_ID AS USER_ID,
BUSINESS_ENTITY_HIER_NAME.IAM_LEVEL_NUM AS LEVEL_NUM,
BUSINESS_ENTITY_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
INNER JOIN BV_SUB_BUSINESS_ENTITY BSE
ON (BUSINESS_ENTITY_NAME=BUSINESS_ENTITY_HIER_NAME)
WHERE BV_IAM_BUSINESS_ENTITY_HIER.IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM=1
AND USER_id=2
GROUP BY 1,2,3,4,5,6
UNION ALL
SELECT BV_USER_BE_HRCHY_TEMP.USER_ID,
BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM AS LEVEL_NUM,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME AS IAM_ENTITY_HIER_NAME,
'Total Development' AS TOTAL_ENGINEERING,
BUSINESS_ENTITY_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
CROSS JOIN BV_USER_BE_HRCHY_TEMP.SUB_BUSINESS_ENTITY_DESCR BSE
WHERE BV_IAM_BUSINESS_ENTITY_HIER.IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM=0
AND USER_ID=?
GROUP BY 1,2,3,4,5,6;
In applicationContext.xml the bean:
<bean id="tablOrclDataSourceRead" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:oci:#********DEV" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="initialSize" value="5" />
<property name="maxActive" value="5" />
<property name="maxIdle" value="0" />
<property name="minIdle" value="0" />
<property name="maxWait" value="-1" />
</bean>
JSON returned:
{"data":[
{"keyCol":"Utah","val":"Utah"},
{"keyCol":"Seattle","val":"Seattle"},
{"keyCol":Nebraska","val":"Nebraska"},
{"keyCol":"Enterprise Networking","val":"Enterprise Networking"}
]}
The time taken to execute the action (and return the JSON) with the above query is around 21 seconds.
Please let me know if I am missing something.
The same query when executed through SQL developer returns the result set in less than a second.

Add text to the start of a SOLR database value

I am using this code for my SOLR DIH:
<dataConfig>
<dataSource name="app" driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/wikipedia" user="wikipedia" password="secret" />
<dataSource name="data" driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/wikipedia" user="wikipedia" password="secret" />
<document>
<entity dataSource="app-ds" name="item" query="SELECT id, title, description, date, link, location_id, source_id, company_id from item">
<field column="id" name="id" />
<field column="title" name="title" />
<field column="description" name="description" />
<field column="date" name="date" />
<field column="link" name="link" />
<entity dataSource="app-ds" name="location" query="SELECT name, coordinate from location where location_id=${item.location_id}">
<field column="name" name="location_name" />
<field column="coordinate" name="location_coordinates" />
</entity>
<entity dataSource="app-ds" name="source" query="SELECT name from source where source_id=${item.source_id}">
<field column="name" name="source_name" />
</entity>
<entity dataSource="app-ds" name="company" query="SELECT name from company where company_id=${item.company_id}">
<field column="name" name="company_name" />
</entity>
</entity>
</document>
</dataConfig>
Since I am merging two databases I want to have a uniqueID for each entry within SOLR. In my case the best way of doing this is to have app*ID* for the first databases ID's and data*ID* for the second databases ID's.
Using my code above, how do I add the word "app" to the front of the ID that is stored in the SOLR ID field so that my database ID=123 and the Solr ID = app123
EDIT: As I guess it might be something like this (but I am not good with SQL)
query="SELECT app_(id)
You can try to modify the SQL Query as -
SELECT 'TABLE1' || ID AS PRIMARY_ID ........
PRIMARY_ID can be now configured as unique ID in solr.
<field column="primary_id" name="primary_id" />
Even if you are performing incremental updates using Delta imports, the SQL ID updated would still generate the Same Solr ID with the above query and would be updated. So be sure to use the above in the Delta queries as well.