While browsing through Oracle Docs, encountered with yet another new feature that Oracle has introduced in the 12c release. Starting from 12c, we can now get to know the actual query that is being executed against the database.
Let me make it simple. We create views to hide complexity; When we query a view, there is no way to get to know the expanded SQL which is being generated at runtime by resolving the view definition.
However, with Oracle Database release 12c; we can easily find, how a query is getting expanded at runtime by the database when I try to query a view. Oracle has introduced a new procedure called EXPAND_SQL_TEXT under the DBMS_UTILITY package, which makes it possible to see what is the actual query that is being executed at runtime.
Though this is not an extraordinary feature, it could be very helpful in certain scenarios like,
1. From a DBA perspective, I can now easily find which all dictionary tables get queried and how it gets queried whenever I query a dictionary view.
2. Debugging a query that has tables which are in turn views of views of views and so on.
3. Another important scenario is with respect to the VPD policies. With the help of the expanded SQL we can now easily find out the filtering condition that is being applied to a query.
Syntax:
The basic syntax for using EXPAND_SQL_TEXT procedure is as follows
DBMS_UTILITY.EXPAND_SQL_TEXT ( input_sql_text IN CLOB, output_sql_text OUT NOCOPY CLOB ); -- input_sql_text = SQL query that needs to be expanded -- output_sql_text = Expanded SQL query that is resulted by resolving the views
Demonstration
Lets see an examples, as to how the procedure expands a given SQL query.
In this example, I am querying the v$session dictionary view.
sys@LABDB> declare 2 expand_sql clob; 3 begin 4 dbms_utility.expand_sql_text ( 5 input_sql_text => 'select sid,serial#,username,status,event from v$session', 6 output_sql_text => expand_sql 7 ); 8 DBMS_OUTPUT.put_line(expand_sql); 9 end; 10 / SELECT "A1"."SID" "SID","A1"."SERIAL#" "SERIAL#","A1"."USERNAME" "USERNAME","A1"."STATUS" "STATUS","A1"."EVENT" "EVENT" FROM (SELECT "A2"."SID" "SID","A2"."SERIAL#" "SERIAL#","A2"."USERNAME" "USERNAME","A2"."STATUS" "STATUS","A2"."EVENT" "EVENT" FROM (SELECT "A5"."INST_ID" "INST_ID","A5"."INDX" "SID","A5"."KSUSESER" "SERIAL#","A5"."KSUUDLNA" "USERNAME",DECODE(BITAND("A5"."KSUSEIDL",11),1,'ACTIVE',0,DECODE(BITAND("A5"."KSUSEFLG",4096),0,'INA CTIVE','CACHED'),2,'SNIPED',3,'SNIPED','KILLED') "STATUS","A4"."KSLEDNAM" "EVENT" FROM SYS."X$KSUSE" "A5",SYS."X$KSLED" "A4",SYS."X$KSLWT" "A3" WHERE BITAND("A5"."KSSPAFLG",1)<>0 AND BITAND("A5"."KSUSEFLG",1)<>0 AND "A5"."INDX"="A3"."KSLWTSID" AND "A3"."KSLWTEVT"="A4"."INDX") "A2" WHERE "A2"."INST_ID"=USERENV('INSTANCE')) "A1" PL/SQL procedure successfully completed.
As we can see, we are presented with the expanded query (actual query) which actually queries the SYS.X$KSUSE, SYS.X$KSLED and SYS.X$KSLWT dictionary tables (hidden under the v$session view).
However, the expanded query generated by EXPAND_SQL_TEXT would not be properly formatted. We need to manually format the expanded query for a better readability. A formatted version of the above expanded query would look something as follows
SELECT A1.SID SID, A1.SERIAL# SERIAL#, A1.USERNAME USERNAME, A1.STATUS STATUS, A1.EVENT EVENT FROM ( SELECT A2.SID SID, A2.SERIAL# SERIAL#, A2.USERNAME USERNAME, A2.STATUS STATUS, A2.EVENT EVENT FROM ( SELECT A5.INST_ID INST_ID, A5.INDX SID, A5.KSUSESER SERIAL#, A5.KSUUDLNA USERNAME, DECODE(BITAND(A5.KSUSEIDL,11),1,'ACTIVE',0, DECODE(BITAND(A5.KSUSEFLG,4096),0,'INACTIVE','CACHED'),2,'SNIPED',3,'SNIPED','KILLED') STATUS, A4.KSLEDNAM EVENT FROM SYS.X$KSUSE A5, SYS.X$KSLED A4, SYS.X$KSLWT A3 WHERE BITAND(A5.KSSPAFLG,1)<>0 AND BITAND(A5.KSUSEFLG,1)<>0 AND A5.INDX=A3.KSLWTSID AND A3.KSLWTEVT=A4.INDX) A2 WHERE A2.INST_ID=USERENV('INSTANCE') ) A1