Skip to Main Content
  • Questions
  • Fetching the type of join, columns used in join and filter for a given select query

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Litty.

Asked: March 24, 2017 - 1:08 pm UTC

Last updated: March 27, 2017 - 5:57 am UTC

Version: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

Viewed 1000+ times

You Asked

Dear Sir,
I have a requirement to parse a given select query to get the columns used in joins, type of joins and filters used.
Can you please suggest how to do this. If this issue was already discussed in this blog, my apologies for raising it once again.

Details:-
Version of Oracle database
=========================================================================================================
BANNER CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production 0
PL/SQL Release 12.1.0.2.0 - Production 0
CORE 12.1.0.2.0 Production 0

TNS for Linux: Version 12.1.0.2.0 - Production 0
NLSRTL Version 12.1.0.2.0 - Production 0
=========================================================================================================

For example, query is like this

SELECT 1 FROM COM_MSG_SUM INNER JOIN RAC_SUG_SUM ON COM_MSG_SUM.CT_KEY = RAC_SUG_SUM.CT_KEY
AND COM_MSG_SUM.DT_KEY = RAC_SUG_SUM.DT_KEY AND
COM_MSG_SUM.ENT_KEY = RAC_SUG_SUM.ENT_KEY INNER JOIN GAL_ENTITY_DTU ON
RAC_SUG_SUM.RAM_KEY= GAL_ENTITY_DTU.RAM_KEY AND RAC_SUG_SUM.ENT_KEY = GAL_ENTITY_DTU.ENT_KEY
AND RAC_SUG_SUM.DATE_KEY = GAL_ENTITY_DTU.DATE_KEY INNER JOIN DIM_DATES ON
DIM_DATES.DATE_KEY = COM_MSG_SUM.DATE_KEY INNER JOIN ORG_CHART ON
ORG_CHART.ENT_KEY = COM_MSG_SUM.ENT_KEY INNER JOIN RUN ON RUN.RAM_KEY = RAC_SUG_SUM.RAM_KEY
INNER JOIN PROD_TYPE ON COM_MSG_SUM.N_PRODUCT_TYPE = PROD_TYPE.PROD_TYPE_IDT LEFT OUTER JOIN ISSUER_DTLS ON
COM_MSG_SUM.ISSUER_ID = ISSUER_DTLS.ISSUER_ID LEFT OUTER JOIN PROD_CLAS ON
RAC_SUG_SUM.CLASS_KEY = PROD_CLAS.CLASS_KEY LEFT OUTER JOIN
ENTITY_TYPE ON GAL_ENTITY_DTU.TYPE_KEY= ENTITY_TYPE.TYPE_KEY LEFT OUTER JOIN DEPTH_TYPE ON
RAC_SUG_SUM.DEPOSIT_TYPE_ID = DEPTH_TYPE.DEPOSIT_TYPE_ID LEFT OUTER JOIN PROD ON
RAC_SUG_SUM.PROD_ID = PROD.PROD_ID AND RUN.RPT_FLG = 'Y'

I have to parse this query and get the column used in joins, type of the join and filters.

Joins Type --- Columns Used in Join --- Filter Used in Select Qyery
------------------------------------------------------------------------------------------------------------------------------
INNER JOIN --- RAC_SUG_SUM ON COM_MSG_SUM.CT_KEY = RAC_SUG_SUM.CT_KEY --- RUN.RPT_FLG = 'Y' [Filter Used in Select Qyery]
INNER JOIN --- COM_MSG_SUM.DT_KEY = RAC_SUG_SUM.DT_KEY
LEFT OUTER JOIN --- RAC_SUG_SUM.DEPOSIT_TYPE_ID = DEPTH_TYPE.DEPOSIT_TYPE_ID
LEFT OUTER JOIN --- RAC_SUG_SUM.PROD_ID = PROD.PROD_ID

Regards
Litty



and Connor said...

You'd need to write your own for that. Something like this should help get you started

SQL> create or replace
  2  function F(p_query varchar2) return sys.odcivarchar2list pipelined is
  3    l_query varchar2(4000) := replace(upper(p_query),chr(10),' ');
  4    pos pls_integer;
  5    joinpos pls_integer;
  6    len pls_integer;
  7    joins sys.odcivarchar2list :=
  8      sys.odcivarchar2list(
  9        'CROSS JOIN',
 10        'NATURAL JOIN',
 11        'LEFT JOIN',
 12        'LEFT OUTER JOIN',
 13        'RIGHT JOIN',
 14        'RIGHT OUTER JOIN',
 15        'INNER JOIN');
 16  begin
 17    pos := instr(p_query,' FROM ');
 18    if pos = 0 then
 19       pipe row ('ERROR: FROM not found');
 20       return;
 21    end if;
 22
 23    l_query := substr(l_query,pos+5);
 24    pos := instr(l_query,' WHERE ');
 25    if pos = 0 then
 26       pipe row ('INFO: WHERE not found');
 27    else
 28      null;
 29    end if;
 30
 31    for x in 1 .. 999 loop 
 32      joinpos := power(2,20);
 33      for i in 1 .. joins.count loop
 34        pos := instr(l_query,joins(i),2);
 35        if pos > 0 then
 36          if pos < joinpos then
 37            joinpos := pos;
 38            len := length(joins(i));
 39          end if;
 40        end if;
 41      end loop;
 42      if joinpos < power(2,20) then
 43        pipe row ( substr(l_query,1,joinpos-1) );
 44        l_query := substr(l_query,joinpos);
 45      end if;
 46    end loop;
 47
 48    return;
 49  end;
 50  /

Function created.

SQL>
SQL> variable q varchar2(4000)
SQL> exec :q := q'{... your query ...}';

PL/SQL procedure successfully completed.

SQL> select * from table(f(:q));

COLUMN_VALUE
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
INFO: WHERE not found
 COM_MSG_SUM
INNER JOIN RAC_SUG_SUM ON COM_MSG_SUM.CT_KEY = RAC_SUG_SUM.CT_KEY AND COM_MSG_SUM.DT_KEY = RAC_SUG_SUM.DT_KEY AND COM_MSG_SUM.ENT_KEY = RAC_SUG_SUM.ENT_KEY
INNER JOIN GAL_ENTITY_DTU ON RAC_SUG_SUM.RAM_KEY= GAL_ENTITY_DTU.RAM_KEY AND RAC_SUG_SUM.ENT_KEY = GAL_ENTITY_DTU.ENT_KEY AND RAC_SUG_SUM.DATE_KEY = GAL_ENTITY_DTU.DATE_KEY
INNER JOIN DIM_DATES ON DIM_DATES.DATE_KEY = COM_MSG_SUM.DATE_KEY
INNER JOIN ORG_CHART ON ORG_CHART.ENT_KEY = COM_MSG_SUM.ENT_KEY
INNER JOIN RUN ON RUN.RAM_KEY = RAC_SUG_SUM.RAM_KEY
INNER JOIN PROD_TYPE ON COM_MSG_SUM.N_PRODUCT_TYPE = PROD_TYPE.PROD_TYPE_IDT
LEFT OUTER JOIN ISSUER_DTLS ON COM_MSG_SUM.ISSUER_ID = ISSUER_DTLS.ISSUER_ID
LEFT OUTER JOIN PROD_CLAS ON RAC_SUG_SUM.CLASS_KEY = PROD_CLAS.CLASS_KEY
LEFT OUTER JOIN ENTITY_TYPE ON GAL_ENTITY_DTU.TYPE_KEY= ENTITY_TYPE.TYPE_KEY
LEFT OUTER JOIN DEPTH_TYPE ON RAC_SUG_SUM.DEPOSIT_TYPE_ID = DEPTH_TYPE.DEPOSIT_TYPE_ID

12 rows selected.


Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Most Useful

Litty Mathew, March 27, 2017 - 5:47 am UTC

Dear Sir,

Tons of Thanks.

Solution suggested is very helpful.

Also i am able to see new things that i was not aware and used before like 'sys.odcivarchar2list pipelined is'.

Once again my heartfelt thanks to the entire Team.
God Bless.

Regards
Litty
Thiruvalla.
Connor McDonald
March 27, 2017 - 5:57 am UTC

Glad we could help

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library