0

I have a requirement to pass a list of employee details (EmpNo, Dept) that is not in a DB table (get from another system as a JSON array). I have to use them in a select query as a table with an inner join. Is this possible in Oracle 11g? If so pls explain.

Please note that I do not have any privilege to create a function or procedure.

ex:

Emp Details :

{"EmpNo":"1", "Dept":1},{"EmpNo":"2", "Dept":1},{"EmpNo":"3", "Dept":2},{"EmpNo":"4", "Dept":2}

SQL:

SELECT * FROM attendance att

INNER JOIN (Emp Details) emp

ON att.EmpNo = emp.EmpNo

WHERE emp.Dept = 1

I found out that it can be done in SQL server as follows, but no luck with oracle

SELECT *  FROM

(VALUES (1,2) , (3,4)

) t1 (c1, c2)

Thanks in advance!

  • with 11g options are extremely limited, possible path is to convert JSON into XML then use 11g xml capabilities. I have seen other suggestions to use install Apex but I have no experience with that: see https://stackoverflow.com/questions/30393214/support-for-json-in-oracle-11g – Paul Maxwell Sep 03 '21 at 05:59
  • @PaulMaxwell Thanks for the comment. I'll check the possibilities and update. – Damith Benaragama Sep 03 '21 at 06:21

2 Answers2

1

Here is code may help you.

SELECT *  FROM
(

(SELECT 1 AS EmpNo,2 AS Dept FROM DUAL)
UNION 
(SELECT 3 AS EmpNo,4 AS Dept FROM DUAL)

) t1
Rick
  • 121
  • 6
  • Dear Rick, Thanks for the reply. However, I'm looking for a solution that can use for a list of values around 2000. So, this might not work for me. Thanks again for the quick reply. – Damith Benaragama Sep 03 '21 at 05:07
1

You can use common table expression with JSON_QUERY() and json_table() as below:

Schema and insert statements:

 create table attendance (EmpNo int,attn_date date);

 insert into attendance values(2,DATE '2021-09-02');

 insert into attendance values(3,DATE '2021-09-03');

Query:

 with emp_json  as  
 ( SELECT JSON_QUERY('[{"EmpNo":"1", "Dept":1},{"EmpNo":"2", "Dept":1},{"EmpNo":"3", "Dept":2},{"EmpNo":"4", "Dept":2}]', '$' ) AS EmpDetails
   FROM DUAL
    
 )   
 SELECT  emp.EmpNo , emp.Dept
 FROM  json_table( (select EmpDetails from emp_json) , '$[*]'  
                 COLUMNS ( EmpNo PATH '$.EmpNo'  
                         , Dept PATH '$.Dept'  
                         )   
                )emp
       inner join attendance att  
       ON att.EmpNo = emp.EmpNo

Output:

EMPNO DEPT
2 1
3 2

db<>fiddle here

For Oracle 11g you can use string manipulation to get your desired result.

Schema and insert statements:

 create table attendance (EmpNo int,attn_date date);

 insert into attendance values(2,DATE '2021-09-02');
 insert into attendance values(3,DATE '2021-09-03');

Query:

 with cte (emp_details) as
 (
    select regexp_substr(replace(replace(replace('[{"EmpNo":"1","Dept":1},{"EmpNo":"2","Dept":1},{"EmpNo":"3","Dept":2},{"EmpNo":"4","Dept":2}]','},{',';'),'[{',''),'}]','')  ,'[^;]+', 1, level) 
    from dual 
    connect BY regexp_substr(replace(replace(replace('[{"EmpNo":"1","Dept":1},{"EmpNo":"2","Dept":1},{"EmpNo":"3","Dept":2},{"EmpNo":"4","Dept":2}]','},{',';'),'[{',''),'}]','')  , '[^;]+', 1, level) 
    is not null
 )
 ,
 cte2 as
 (
   select regexp_replace(regexp_substr(emp_details, '[^,]+', 1, 1),'[^0-9]','') as EmpNo, 
          regexp_replace(regexp_substr(emp_details, '[^,]+', 1, 2),'[^0-9]','') as Dept
   from cte
 )
 select emp.EmpNo,emp.Dept
  from cte2 emp
  inner join attendance att  
        ON att.EmpNo = emp.EmpNo

Output:

EMPNO DEPT
2 1
3 2

db<>fiddle here

  • Many Thanks Kazi, This is what I looked for. However, for my bad luck, my oracle version is 11g is not supporting these functions. _ORA-00904: "JSON_QUERY": invalid identifier_ . Thanks for your Answer. – Damith Benaragama Sep 03 '21 at 05:34
  • Will try to find solution for that version. – Kazi Mohammad Ali Nur Romel Sep 03 '21 at 06:09
  • Thanks @Kazi. I can convert the Emp Details to ('1',1), ('2',1),('3',2),('4',2) if needed. if you have a solution for it. – Damith Benaragama Sep 03 '21 at 07:10
  • 1
    `'02-SEP-21'` may look like a date but it is not; it is a string literal. Oracle will try to implicitly convert a string literal to a date using the `NLS_DATE_FORMAT` session parameter but this is not guaranteed to work as any user can change their own session parameters at any time (even worse, if the `NLS_DATE_FORMAT` is `YYYY-MM-DD` then it will work but give an unexpected result of 21st September 0002 BC) so relying on implicit conversion is bad practice. Much better is to use a date literal `DATE '2021-09-02'`. – MT0 Sep 03 '21 at 08:20
  • Thanks @MT0. I have revised my answer. – Kazi Mohammad Ali Nur Romel Sep 03 '21 at 09:16
  • @DamithBenaragama I have added another answer for Oracle 11g. If you need any clarification then please feel free to ask. – Kazi Mohammad Ali Nur Romel Sep 03 '21 at 10:51