Oracle XML DB with XMLEXISTS don't work with xmlns on root XML - oracle-xml-db

I have a table with XMLTYPE column and the XMLEXIST works fine.
But when the root element have a xmlns atribute the XMLEXISTS don't find the record what i'm looking for.
Without the xmlns attribute the XMLEXISTS works fine.
What's wrong?
Example:
<employe>
<employe_id>12345</employe_id>
<employe_name>John</employe_name>
</employe>
The Query:
SELECT count(*) FROM mytable
WHERE XMLEXISTS('/employe[employe_id="12345"]'
PASSING xmltype_col
)
Result: 1
But with xmlns attribute on the root element the query return 0.
<employe xmlns="http://www.example.com/version_01_01_00">
<employe_id>12345</employe_id>
<employe_name>John</employe_name>
</employe>
The mytable is schemaless.

After much research, I discovered the solution.
select *
from (
select
xmlelement("employe",
XMLATTRIBUTES('www.example.com/version_01_01_00' as "xmlns") ,
xmlforest(
'12345' as "employe_id",
'John' as "employe_name"
)
) test
from dual
) x
where XMLEXISTS(
'declare default element namespace "www.example.com/version_01_01_00"; (::)
/employe[employe_id="12345"]'
PASSING test
)

Related

How to use a recursive query in a subquery in PostgreSQL

I created a recursive query that returns me a string of the productcategory history (typical parent-child relation:
with recursive productCategoryHierarchy as (
--start with the "anchor" row
select
1 as "level",
pg1.id,
pg1.title,
pg1.parentproductgroup_id
from product_group pg1
where
pg1.id = '17e949b6-85b3-4c87-8f76-ad1e61ea01e1' --parameterize me
union all
-- Get child nodes
select
pch.level +1 as "level",
pg2.id,
pg2.title,
pg2.parentproductgroup_id
from product_group pg2
join productCategoryHierarchy pch on pch.parentproductgroup_id = pg2.id
)
-- Get hierarchy as string
select
CONCAT('',string_agg(productCategoryHierarchy.title, ' > '),'')
from productCategoryHierarchy;
Now I want to use this result in another query as a subquery so that I can use the created string as an attribute in the parent query. Is that possible in Postgres or is there another solution to get a hierarchical tree as string in an attribute?
Are you looking for something like this?
with recursive productcategoryhierarchy as (
...
), aggregated_values as (
select string_agg(productCategoryHierarchy.title, ' > ') as all_titles
from productCategoryHierarchy
)
select ..., (select all_titles from aggregated_values) as all_titles
from ... your main query goes here ..

T-SQL XML do not return element if no child elements

I do not want to return a Xml element if no child elements exists:
SELECT
(
SELECT
'nl' AS [#Language]
,'test' AS [#Value]
WHERE 1=0
FOR XML PATH('Translation'), ROOT('Translations'), TYPE
)
FOR XML RAW('IngredientStatement'), TYPE
In this case <IngredientStatement /> is returned.
One way to do it is to separate the inner select into a common table expression:
;WITH InnerXmlCte AS
(
SELECT
(
SELECT
'nl' AS [#Language]
,'test' AS [#Value]
WHERE 1=0
FOR XML PATH('Translation'), TYPE
) As Translations
)
SELECT Translations
FROM InnerXmlCte
WHERE Translations IS NOT NULL
FOR XML RAW('IngredientStatement'), TYPE
Another approach was to add an XQuery, filtering for <IngredientStatement> with any content:
SELECT
(
SELECT
(
SELECT
'nl' AS [#Language]
,'test' AS [#Value]
WHERE 1=0
FOR XML PATH('Translation'), ROOT('Translations'), TYPE
)
FOR XML RAW('IngredientStatement'), TYPE
).query('/IngredientStatement[*]')

understanding complex SP in DB2

I need to make changes to an SP which has a bunch of complex XML functions and what not
Declare ResultCsr2 Cursor For
WITH
MDI_BOM_COMP(PROD_ID,SITE_ID, xml ) AS (
SELECT TC401F.T41PID,TC401F.T41SID,
XMLSERIALIZE(
XMLAGG(
XMLELEMENT( NAME "MDI_BOM_COMP",
XMLFOREST(
trim(TC401F.T41CTY) AS COMPONENT_TYPE,
TC401F.T41LNO AS COMP_NUM,
trim(TC401F.T41CTO) AS CTRY_OF_ORIGIN,
trim(TC401F.T41DSC) AS DESCRIPTION,
TC401F.T41EFR AS EFFECTIVE_FROM,
TC401F.T41EFT AS EFFECTIVE_TO,
trim(TC401F.T41MID) AS MANUFACTURER_ID,
trim(TC401F.T41MOC) AS MANUFACTURER_ORG_CODE,
trim(TC401F.T41CNO) AS PROD_ID,
trim(TC401F.T41POC) AS PROD_ORG_CODE,
TC401F.T41QPR AS QTY_PER,
trim(TC401F.T41SBI) AS SUB_BOM_ID,
trim(TC401F.T41SBO) AS SUB_BOM_ORG_CODE, --ADB01
trim(TC401F.T41VID) AS SUPPLIER_ID,
trim(TC401F.T41SOC) AS SUPPLIER_ORG_CODE,
TC401F.T41UCT AS UNIT_COST
)
)
) AS CLOB(1M)
)
FROM TC401F TC401F
GROUP BY T41PID,T41SID
)
SELECT
RowNum, '<BOM_INBOUND>' ||
XMLSERIALIZE (
XMLELEMENT(NAME "INTEGRATION_MESSAGE_CONTROL",
XMLFOREST(
'FULL_UPDATE' as ACTION,
'POLARIS' as COMPANY_CODE,
TRIM(TC400F.T40OCD) as ORG_CODE,
'5' as PRIORITY,
'INBOUND_ENTITY_INTEGRATION' as MESSAGE_TYPE,
'POLARIS_INTEGRATION' as USERID,
'TA' as RECEIVER,
HEX(Generate_Unique()) as SOURCE_SYSTEM_TOKEN
),
XMLELEMENT(NAME "BUS_KEY",
XMLFOREST(
TRIM(TC400F.T40BID) as BOM_ID,
TRIM(TC400F.T40OCD) as ORG_CODE
)
)
) AS VARCHAR(1000)
)
|| '<MDI_BOM>' ||
XMLSERIALIZE (
XMLFOREST(
TRIM(TC400F.T40ATP) AS ASSEMBLY_TYPE,
TRIM(TC400F.T40BID) AS BOM_ID,
TRIM(TC400F.T40CCD) AS CURRENCY_CODE,
TC400F.T40DPC AS DIRECT_PROCESSING_COST,
TC400F.T40EFD AS EFFECTIVE_FROM,
TC400F.T40EFT AS EFFECTIVE_TO,
TRIM(TC400F.T40MID) AS MANUFACTURER_ID,
TRIM(TC400F.T40MOC) AS MANUFACTURER_ORG_CODE,
TRIM(TC400F.T40OCD) AS ORG_CODE,
TRIM(TC400F.T40PRF) AS PROD_FAMILY,
TRIM(TC400F.T40PID) AS PROD_ID,
TRIM(TC400F.T40POC) AS PROD_ORG_CODE,
TRIM(TC400F.T40ISA) AS IS_ACTIVE,
TRIM(TC400F.T40VID) AS SUPPLIER_ID,
TRIM(TC400F.T40SOC) AS SUPPLIER_ORG_CODE,
TRIM(TC400F.T40PSF) AS PROD_SUB_FAMILY,
CASE TRIM(TC400F.T40PML)
WHEN '' THEN TRIM(TC400F.T40PML)
ELSE TRIM(TC400F.T40PML) || '~' || TRIM(TC403F.T43MDD)
END AS PROD_MODEL
) AS VARCHAR(3000)
)
|| IFNULL(MBC.xml, '') ||
XMLSERIALIZE (
XMLFOREST(
XMLFOREST(
TRIM(TC400F.T40CCD) AS CURRENCY_CODE,
TC400F.T40PRI AS PRICE,
TRIM(TC400F.T40PTY) AS PRICE_TYPE
) AS MDI_BOM_PRICE,
XMLFOREST(
TRIM(TC400F.T40CCD) AS CURRENCY_CODE,
TRIM(TC400F.T40PRI) AS PRICE,
'TRANSACTION_VALUE' AS PRICE_TYPE
) AS MDI_BOM_PRICE,
XMLFOREST(
TRIM(TC400F.T40INA) AS INCLUDE_IN_AVERAGING
) AS MDI_BOM_IMPL_BOM_PROD_FAMILY_AUTOMOBILES
) AS VARCHAR(3000)
)
|| '</MDI_BOM>' ||
'</BOM_INBOUND>' XML
FROM (
SELECT
ROW_NUMBER() OVER (
ORDER BY T40STS
,T40SID
,T40BID
) AS RowNum
,t.*
FROM TC400F t
) TC400F
LEFT OUTER JOIN MDI_BOM_COMP MBC
ON TC400F.T40SID = MBC.SITE_ID
AND TC400F.T40PID = MBC.PROD_ID
LEFT OUTER JOIN TC403F TC403F
ON TC400F.T40PML <> ''
AND TC400F.T40PML = TC403F.T43MDL
WHERE TC400F.T40STS = '10'
AND TC400F.RowNUM BETWEEN
(P_STARTROW + (P_PAGENOS - 1) * P_NBROFRCDS)
AND (P_STARTROW + (P_PAGENOS - 1) * P_NBROFRCDS +
P_NBROFRCDS - 1);
Given above is a cursor declaration in the SP code which I am struggling to understand. The very first WITH itself seems to be mysterious. I have used it along with temporary table names but this is the first time, Im seeing something of this sort which seems to be an SP or UDF? Can someone please guide me on how to understand and make sense out of all this?
Adding further to the question, the actual requirement here is to arrange the data in the XML such a way that that those records which have TC401F.T41SBI field populated should appear in the beginning of the XML output..
This field is being selected as below in the code:
trim(TC401F.T41SBI) AS SUB_BOM_ID. If this field is non-blank, this should appear first in the XML and any records with this field value Blank should appear only after. What would be the best approach to do this? Using ORDER BY in any way does not really seem to help as the XML is actually created through some functions and ordering by does not affect how the items are arranged within the XML. One approach I could think of was using a where clause where TC401F.T41SBI <> '' first then append those records where TC401F.T41SBI = ''
Best I can do is help with the CTE.
WITH
MDI_BOM_COMP(PROD_ID,SITE_ID, xml ) AS (
SELECT TC401F.T41PID,TC401F.T41SID,
This just generates a table named MDI_BOM_COMP with three columns named PROD_ID, SITE_ID, and XML. The table will have one record for each PROD_ID, SITE_ID, and the contents of XML will be an XML snippet with all the components for that product and site.
Now the XML part can be a bit confusing, but if we break it down into it's scalar and aggregate components, we can make it a bit more understandable.
First ignore the grouping. so the CTE retrieves each row in TC401F. XMLELEMENT and XMLFORREST are scalar functions. XMLELEMENT creates a single XML element The tag is the first parameter, and the content of the element is the second in the above example. XMLFORREST is like a bunch of XMLELEMENTs concatenated together.
XMLSERIALIZE(
XMLAGG(
XMLELEMENT( NAME "MDI_BOM_COMP",
XMLFOREST(
trim(TC401F.T41CTY) AS COMPONENT_TYPE,
TC401F.T41LNO AS COMP_NUM,
trim(TC401F.T41CTO) AS CTRY_OF_ORIGIN,
trim(TC401F.T41DSC) AS DESCRIPTION,
TC401F.T41EFR AS EFFECTIVE_FROM,
TC401F.T41EFT AS EFFECTIVE_TO,
trim(TC401F.T41MID) AS MANUFACTURER_ID,
trim(TC401F.T41MOC) AS MANUFACTURER_ORG_CODE,
trim(TC401F.T41CNO) AS PROD_ID,
trim(TC401F.T41POC) AS PROD_ORG_CODE,
TC401F.T41QPR AS QTY_PER,
trim(TC401F.T41SBI) AS SUB_BOM_ID,
trim(TC401F.T41SBO) AS SUB_BOM_ORG_CODE, --ADB01
trim(TC401F.T41VID) AS SUPPLIER_ID,
trim(TC401F.T41SOC) AS SUPPLIER_ORG_CODE,
TC401F.T41UCT AS UNIT_COST
)
)
) AS CLOB(1M)
So in the example, for each row in the table, XMLFORREST creates a list of XML elements, one for each of COMPONENT_TYPE, COMP_NUM, CTRY_OF_ORIGIN, etc. These elements form the content of another XML element MDI_BOM_COMP which is created by XMLELEMENT.
Now for each row in the table we have selected PROD_ID, SITE_ID, and created some XML. Next we group by PROD_ID, and SITE_ID. The aggregation function XMLAGG will collect all the XML for each PROD_ID and SITE_ID, and concatenate it together.
Finally XMLSERIALIZE will convert the internal XML representation to the string format we all know and love ;)
I think I found the answer for my requirement. I had to add an order by field name after XMLELEMENT function

Variable in comma separated in the IN CLAUSE of SP of DB2 for Z/OS

I have a SP in which I have a In clause like mentioned below
value1 is a Int,Variable1 is varchar
Suppose SP started
Variable1=(value1,value2,value3)--getting from another table
Select * from tableA where Column1 in (Variable1).
The just above statement is not working ,needed a work around for this ,Please help
Here is a small example of using an XML list to select an arbitrary number of values:
SELECT * FROM "tableA"
WHERE "Column1" IN (
SELECT * FROM
XMLTABLE('$X/set/row' PASSING XMLPARSE('
<set>
<row item="1"/>
<row item="2"/>
<row item="3"/>
<!-- add as many "row" as you need here -->
</set>
')
AS "X"
COLUMNS
"item" INT PATH '#item'
) AS X
)
Then you can parameterize the query, where ? is a parameter of type XML
SELECT * FROM "tableA"
WHERE "Column1" IN (
SELECT * FROM
XMLTABLE('$X/set/row' PASSING ? AS "X" COLUMNS "item" INT PATH '#item') AS X
)

Microsoft Report Builder with Postgresql and multiple CTEs

I have a problem creating DataSets with CTE in the current Microsoft Report Designer.
My DataSource is a PostgreSQL Database and I use the current Version of PGNP to connect to.
The connection works fine, I can create DataSets based on Queries and get my data.
BUT if I try to create more complex queries, like for example with multiple CTE, I won't get any fields.
Exampe:
SELECT 'Test' as test
Will return one column (test) with one row (Test)
WITH Test as (SELECT 'Test' as test)
SELECT Test
, 'Success' as result
FROM Test
Will return two columns (test, result) with one row (Test, Success)
Till now, everything is ok.
But if I want to use more then one CTE, I have to face the following problems:
WITH Test as (SELECT 'Test' as test),
TestB as (SELECT 'Test B' as test)
SELECT ta.test, tb.test, 'Success' as result
FROM Test ta, TestB tb
Will fail with the following error message:
"Undefined table Test"
;WITH Test as (SELECT 'Test' as test),
TestB as (SELECT 'Test B' as test)
SELECT ta.test, tb.test, 'Success' as result
FROM Test ta, TestB tb
Will return no columns and no rows.
Any idea why this happens?
Edit A:
Here a (shorternd) Version of my actual query:
WITH calls AS (
SELECT acv.id
, acv.created
, acv.state
, acv.statistics_category
, acv.duration
, aqv.id as queue_id
, aqv.name as queue_name
, acv.target
, acv.target_name
, acv.queue_time
, acv.ringing_duration
, acv.hold_time
FROM acd_call_view acv
LEFT JOIN acd_queue_view aqv ON (aqv.id = acv.fk_acdqueue_id)
ORDER BY acv.id, acv.created
),
calls_answered as (
SELECT *
FROM calls
WHERE statistics_category = 'answered'
)
SELECT * FROM calls_answered
Result: "Unknown table calls"
Edit B:
Sorry, had two leftovers from the shortening remaining in the query
Edit C:
Tested Query in pgAdmin III: Working
Tested Query in JasperSoft Studio: Working
Tested Query in MS Report Builder with PGNP: "Undefined table calls"
Edit D:
As soon as I remove the second CTE, I get results
WITH calls AS (
SELECT acv.id
, acv.created
, acv.state
, acv.statistics_category
, acv.duration
, aqv.id as queue_id
, aqv.name as queue_name
, acv.target
, acv.target_name
, acv.queue_time
, acv.ringing_duration
, acv.hold_time
FROM acd_call_view acv
LEFT JOIN acd_queue_view aqv ON (aqv.id = acv.fk_acdqueue_id)
ORDER BY acv.id, acv.created
)
SELECT * FROM calls
Works fine, so I get results, the PGNP Ole DB Driver seems to work fine, the connection is up, everything is okay.
As soon, as I add the second CTE, I get the error
Works here (just plain psql terminal) , so the error must be in your framework/client application:
CREATE TABLE acd_call_view
( id INTEGER NOT NULL
, created timestamp
, state integer
, statistics_category text
, duration INTEGER
, target INTEGER
, target_name INTEGER
, queue_time INTEGER
, ringing_duration INTEGER
, hold_time INTEGER
, fk_acdqueue_id INTEGER
);
CREATE TABLE acd_queue_view
( id INTEGER NOT NULL
, name text
);
WITH calls AS (
SELECT acv.id
, acv.created
, acv.state
, acv.statistics_category
, acv.duration
, aqv.id as queue_id
, aqv.name as queue_name
, acv.target
, acv.target_name
, acv.queue_time
, acv.ringing_duration
, acv.hold_time
FROM acd_call_view acv
LEFT JOIN acd_queue_view aqv ON aqv.id = acv.fk_acdqueue_id
ORDER BY acv.id, acv.created
)
, calls_answered as (
SELECT *
FROM calls
WHERE statistics_category = 'answered'
)
SELECT * FROM calls_answered
;
Okay, here the solution:
Seems like the PGNP OleDB Driver cannot handle multiple CTEs.
Installed the ODBC Driver and configured a new DateSource via ODBC.
Now I get my results and am happy :-)
Nevertherless, thank you joop for your time.
I contacted PGNP support, and they responded quickly that the bugs in the CTEs handling were fixed in build 1.4.0.3425.