Santosh Raviteja
3 min readJun 15, 2021

--

How to pass array of JSON values to oracle Query Using XQUERY.

One can come across a scenario for generating a SQL query or any query with the randomly passed array of input values in the WHERE clause.

Eg:

The below JSON variable — ControllingPU contains array of values.

“ControllingPU”: [“011385”,”011914"]

The values — 011385 and 011914 are required to be applied in the WHERE condition of SQL Query. This can be achieved using IN Clause in the WHERE conditions. But how to achieve the format and add the values randomly where SQL understands and parse the same???

Expected SQL Query:

SELECT * FROM <<Table_Name>> WHERE PROJECT_PU in (‘011385’,’011914’);- — — -Framing the WHERE condition using IN Clause.

PROJECT_PU values will filter the data in <<Table_Name>> and return the desired result which user is interested to look into.

This challenge can be resolved with the below generic XQUERY code snippet.

Code:

let $columns :=<root>

<ControllingPU>PROJECT_PU</ControllingPU> (: Line A :)

</root>

return

let $payload :=util:parseXML(util:toXML($input.PORdd))

return

let $condition :=””

for $filter at $index in fn:distinct-values($input.PORdd/*[.!=’’]/name())

return

if($index != fn:count(fn:distinct-values($input.PORdd/*[.!=’’]/name())))

then

for $case at $in in ($payload/*[name()=$filter]/text())

return

if(fn:count($payload/*[name()=$filter]/text()) = 1)

then

$condition ||$columns/*[name()=$filter]/text() ||” in (‘“ || fn:string-join($case, “,”) || “‘“||”’)”

else

if($in = 1)

then

$condition || $columns/*[name()=$filter]/text() ||” in (‘“|| fn:string-join($case, “,”) || “‘“||”,”

else

if($in != fn:count($payload/*[name()=$filter]/text()))

then

$condition || “‘“ || fn:string-join($case, “,”) || “‘“||”,”

else

$condition || “‘“ || fn:string-join($case, “,”) || “‘) and “

else

for $case at $in in ($payload/*[name()=$filter]/text())

return

if(fn:count($payload/*[name()=$filter]/text()) = 1)

then

$condition ||$columns/*[name()=$filter]/text() ||” in (‘“ || fn:string-join($case, “,”) || “‘“||”’)”

else

if($in = 1)

then

$condition || $columns/*[name()=$filter]/text() ||” in (‘“|| fn:string-join($case, “,”) || “‘“||”,”

else

if($in != fn:count($payload/*[name()=$filter]/text()))

then

$condition || “‘“ || fn:string-join($case, “,”) || “‘“||”,”

else

$condition || “‘“ || fn:string-join($case, “,”) || “‘)”

The above code returns a TEXT value by framing the IN Clause = “PROJECT_PU in (‘011385’,’011914’)”

Points to remember while using the XQUERY code → (: Line A :) -> 2nd line in the code

1. XQUERY is generic and can work for any number of variables with array of values.

If the user wants to add another variable like PROJECT_NUMBER then frame the JSON as below –

JSON Input –

{

“ControllingPU”: [“011385”,”011914"],

“ProjectNumber”:[“ABCD”,”PQRS”]

}

2. To handle the additional variables like ProjectNumber, XQUERY needs to be modified like below- Go to the line — (: Line A :) and add another line like below

let $columns :=<root>

<ControllingPU>PROJECT_PU</ControllingPU> (: Line A :)

<ProjectNumber>PROJECT_NUMBER</ProjectNumber>

</root>

Here PROJECT_PU and PROJECT_NUMBER should be the actual fields names available in the table and the parent tags <ControllingPU> and <ProjectNumber> Should match with the JSON input.

After the customizations, XQUERY returns the output like below –

Output — PROJECT_PU in (‘011385’,’011914’) and PROJECT_NUMBER in (‘ABCD’,’PQRS’)

Capture the Output in to a variable — “v_output” and the pass the same in SQL statement.

SQL Query — SELECT * FROM <<TABLE_NAME>> WHERE {$v_output};

Which gets decoded to below during the run time.

SELECT * FROM <<TABLE_NAME>> WHERE PROJECT_PU in (‘011385’,’011914’) and PROJECT_NUMBER in (‘ABCD’,’PQRS’);

This generic XQUERY code can be invoked in any of the XQUERY editor and generate the desired result.

Happy Coding!!!

--

--

Santosh Raviteja

Data evangelist, CSM, The views expressed here are my own and do not necessarily reflect the views of any organization. Favorite quote: This too shall pass away