Home » SQL & PL/SQL » SQL & PL/SQL » Function that returns source tables from a query (Oracle 11g)
Function that returns source tables from a query [message #598656] Wed, 16 October 2013 12:30 Go to next message
mertez
Messages: 9
Registered: August 2013
Location: slo
Junior Member
I am interested if there maybe exists any function that would return all source tables that are present in the given sql. For example function('select 'abc' from table_1, table2') would return a list containing 'table_1' and 'table_2'.

Thank you

[Updated on: Wed, 16 October 2013 12:31]

Report message to a moderator

Re: Function that returns source tables from a query [message #598657 is a reply to message #598656] Wed, 16 October 2013 12:36 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Look at *_DEPENDENCIES, where * could be - user, all and dba.

USER_DEPENDENCIES
Re: Function that returns source tables from a query [message #598658 is a reply to message #598657] Wed, 16 October 2013 12:50 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

How *_DEPENDENCIES will return the dependencies of a QUERY?

Re: Function that returns source tables from a query [message #598659 is a reply to message #598658] Wed, 16 October 2013 13:01 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
Gee...OP said sql? I saw the function, thought he needs the tables used in the function. But why would need another query to see the tables used in a sql? It would be easily visible in the FROM clause.

I meant this -

SQL> create table t(a number);

Table created.

SQL>
SQL> create or replace function f
  2  return number
  3  as
  4  v number;
  5  begin
  6  select count(*) into v from t;
  7  return v;
  8  end;
  9  /

Function created.

SQL>
SQL> show errors;
No errors.
SQL>
SQL> select name,referenced_name,referenced_type from user_dependencies where 
name='F' and referenced_owner='SCOTT';

NAME                           REFERENCED_NAME                                                  REFERENCED_TYPE    
------------------------------ ---------------------------------------------------------------- ------------------ 
F                              T                                                                TABLE              
icon14.gif  Re: Function that returns source tables from a query [message #598660 is a reply to message #598658] Wed, 16 October 2013 13:01 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
Or maybe this way:
SQL> create or replace function get_sql_dependencies (p_sql in varchar2)
  2  return sys.odcivarchar2list
  3  pipelined
  4  is
  5    pragma autonomous_transaction;
  6  begin
  7    execute immediate 'create or replace view "get_sql_dependencies_view" as '||p_sql;
  8    for rec in (
  9     select REFERENCED_OWNER, REFERENCED_NAME, REFERENCED_TYPE
 10     from user_dependencies
 11     where name = 'get_sql_dependencies_view'
 12    ) loop
 13     pipe row (rec.REFERENCED_OWNER||'.'||reC.REFERENCED_NAME||' ('||rec.REFERENCED_TYPE||')');
 14    end loop;
 15  end;
 16  /

Function created.

SQL> select * from table(get_sql_dependencies ('select * from t1, t2 where col1a=col2a'));
COLUMN_VALUE
------------------------------------------------------------------------------------
MICHEL.T1 (TABLE)
MICHEL.T2 (TABLE)

Re: Function that returns source tables from a query [message #598661 is a reply to message #598659] Wed, 16 October 2013 13:03 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Quote:
It would be easily visible in the FROM clause.


And if the query contains views or function referencing tables or...
In addition, it is not always visible (just have a look at the many queries that are posted here).

[Updated on: Wed, 16 October 2013 13:04]

Report message to a moderator

icon14.gif  Re: Function that returns source tables from a query [message #598662 is a reply to message #598661] Wed, 16 October 2013 13:06 Go to previous messageGo to next message
Lalit Kumar B
Messages: 3174
Registered: May 2013
Location: World Wide on the Web
Senior Member
For that matter, you have already given a perfect solution above /forum/fa/2115/0/
Re: Function that returns source tables from a query [message #598664 is a reply to message #598662] Wed, 16 October 2013 13:47 Go to previous messageGo to next message
mertez
Messages: 9
Registered: August 2013
Location: slo
Junior Member
Actually the thing is that some of our queries are quite big and has many subselects so searching for source tables is painless. Because of that I am looking for an automated way for searching them.

So if I understand correctly there is no way to check dependencies on the fly (with an sql string) but you first have to create a view or some other object and after that check for all dependencies? Probably this would be the most logical thing to do..

It would be interesting to know how does the query planner find dependencies between tables. There is a similar problem...

ps: thanks for the solution

[Updated on: Wed, 16 October 2013 13:48]

Report message to a moderator

Re: Function that returns source tables from a query [message #598668 is a reply to message #598660] Wed, 16 October 2013 14:28 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Michel Cadot wrote on Wed, 16 October 2013 14:01
Or maybe this way:


It will work, but not in all cases. View can't be created from every query. For starters view can't be created if select list expression isn't aliased:

SCOTT@orcl > create or replace
  2            view v1
  3              as
  4                select  1
  5                  from  dual
  6  /
              select  1
                      *
ERROR at line 4:
ORA-00998: must name this expression with a column alias


SCOTT@orcl > 


Or privilege issue. User simply might not have CREATE VIEW privilege. Or user can have SELECT privilege on query table(s) but via role and therefore view can't be created. Thera are possible more cases when view can't be created.

SY.
icon14.gif  Re: Function that returns source tables from a query [message #598681 is a reply to message #598668] Wed, 16 October 2013 15:04 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Yes, this was a starter to see if OP wants to investigate this way.
We can (and should) create the function with AUTHID CURRENT_USER to avoid privileges problem but the CREATE VIEW one.
We can also use DBMS_SQL to parse the query and get the columns and so create a view listing the appropriate number and types of columns.
We can also go deeper in the dependencies with a hierarchical query on ALL_DEPENDENCIES.
...

Re: Function that returns source tables from a query [message #598708 is a reply to message #598681] Wed, 16 October 2013 18:18 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Michel Cadot wrote on Wed, 16 October 2013 16:04

We can (and should) create the function with AUTHID CURRENT_USER to avoid privileges problem but the CREATE VIEW one.



Not sure how this will help. AUTHID CURRENT_USER will help to select from a table where user has SELECT privilege granted via role. It will not help to create a view on such table. CREATE VIEW prereq is directly granted SELECT privilege.

SY.
Re: Function that returns source tables from a query [message #598717 is a reply to message #598708] Thu, 17 October 2013 00:37 Go to previous messageGo to next message
Michel Cadot
Messages: 68643
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator
Quote:
It will not help to create a view on such table. CREATE VIEW prereq is directly granted SELECT privilege.


Nope:
SQL> create or replace function get_sql_dependencies (p_sql in varchar2)
  2  return sys.odcivarchar2list
  3  authid current_user
  4  pipelined
  5  is
  6    pragma autonomous_transaction;
  7  begin
  8    execute immediate 'create or replace view "get_sql_dependencies_view" as '||p_sql;
  9    for rec in (
 10     select REFERENCED_OWNER, REFERENCED_NAME, REFERENCED_TYPE
 11     from user_dependencies
 12     where name = 'get_sql_dependencies_view'
 13    ) loop
 14     pipe row (rec.REFERENCED_OWNER||'.'||reC.REFERENCED_NAME||' ('||rec.REFERENCED_TYPE||')');
 15    end loop;
 16  end;
 17  /

Function created.

SQL> create role r;

Role created.

SQL> grant create table, create view to r;

Grant succeeded.

SQL> grant execute on GET_SQL_DEPENDENCIES to r;

Grant succeeded.

SQL> create user test identified by test default tablespace ts_d01 quota unlimited on ts_d01;

User created.

SQL> grant create session to test;

Grant succeeded.

SQL> grant r to test;

Grant succeeded.

SQL> connect test/test
Connected.
TEST> create table t (col int);

Table created.

TEST> select * from table(michel.get_sql_dependencies ('select * from t'));
COLUMN_VALUE
--------------------------------------------------------------------------
TEST.T (TABLE)

TEST> select object_name, object_type from user_objects;
OBJECT_NAME                    OBJECT_TYPE
------------------------------ -------------------
get_sql_dependencies_view      VIEW
T                              TABLE

The view was created by the function.


Re: Function that returns source tables from a query [message #598738 is a reply to message #598717] Thu, 17 October 2013 05:22 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member

Michel Cadot wrote on Thu, 17 October 2013 01:37
Nope:


It is not what I said. In your example user owns table T, while I was talking about user has SELECT via role on a table in some other schema. Try the following:

1) User U1 owns table T.
2) User U2 has CREATE VIEW privilege.
3) User U2 has execute on function GET_SQL_DEPENDENCIES
4) User U2 is granted SELECT on U1.T via role R.
5) User U2 wants to find all tables involved in SELECT * FROM U1.T

SY.

[Updated on: Thu, 17 October 2013 05:29]

Report message to a moderator

Re: Function that returns source tables from a query [message #598744 is a reply to message #598738] Thu, 17 October 2013 06:20 Go to previous messageGo to next message
ThomasG
Messages: 3211
Registered: April 2005
Location: Heilbronn, Germany
Senior Member
Another option that came to mind:

Would running an explain plan for the query, and then checking the plan table work?

In object_name and object_type of the plan_table you would have either directly the tables that are used in the query, or indexes belonging to the tables used.
Re: Function that returns source tables from a query [message #599084 is a reply to message #598744] Tue, 22 October 2013 02:39 Go to previous message
ThomasG
Messages: 3211
Registered: April 2005
Location: Heilbronn, Germany
Senior Member
Just did the "explain plan way" out of curiosity, which might be more "multi-user-friendly" than creating a view:

SQL> create or replace function get_sql_dependencies (p_sql in varchar2)
  2      return sys.odcivarchar2list
  3      pipelined
  4      is
  5        pragma autonomous_transaction;
  6      BEGIN
  7        execute immediate 'DELETE FROM plan_table';
  8        execute immediate 'explain plan for '||p_sql;
  9        COMMIT;
 10        for rec in (
 11        SELECT DISTINCT OBJECT_OWNER, object_name, OBJECT_TYPE
 12          FROM plan_table WHERE object_type = 'TABLE'
 13         UNION
 14        SELECT DISTINCT table_owner, TABLE_NAME, '(Via Index)'
 15          FROM plan_table
 16          join all_indexes ON index_name = object_name
 17       ) loop
 18       pipe row (
 19         rec.OBJECT_OWNER||'.'||reC.object_name||' ('||rec.OBJECT_TYPE||')'
 20       );
 21      end loop;
 22    end;
 23  /

Function created.

SQL>
SQL>
SQL> SELECT * FROM TABLE(get_sql_dependencies('select * from dual'));

COLUMN_VALUE
--------------------------------------------------------------------------------

SYS.DUAL (TABLE)

[Updated on: Tue, 22 October 2013 02:40]

Report message to a moderator

Previous Topic: PL/SQL Error
Next Topic: How to create table replica dynamically
Goto Forum:
  


Current Time: Tue Apr 23 11:37:57 CDT 2024