How to know if a db-link is used somewhere in a DB - oracle

I would like to know if it exists an Oracle command to know if a DB-LINK (name: myBDLink) is used somewhere in a DB and how to display the objects (views,materialized views, procedures, functions, ...) which use it.
Could you please help me with that ?
Thanks for your help

Well, you could try to query various system views and see whether any of them contains a string you're looking for. As you want to check the whole database, you'll probably connect as a privileged user and check dba_ views; otherwise, all_ or user_ would do.
For example, to check procedures, functions, packages, ...:
select owner, name, type, line
from dba_source
where owner not in ('SYS', 'SYSTEM')
and lower(text) like '%mydblink%';
To check views, you'll need a function which will search through its LONG datatype column (as you can't use it directly in SQL):
create or replace function f_long(par_view in varchar2, par_String in varchar2)
return varchar2
is
l_text varchar2(32000);
begin
select text
into l_text
from dba_views
where owner not in ('SYS', 'SYSTEM')
and view_name = par_view;
return case when instr(lower(l_text), lower(par_string)) > 0 then 1
else 0
end;
end;
/
and then
select owner, view_name
from dba_views
where f_long(view_name, 'mydblink') = 1;
I excluded SYS and SYSTEM as they should not contain anything of users' stuff. Perhaps you'd want to exclude some more users.
To see some more (re)sources, query the dictionary, e.g.
select table_name, comments
from dictionary;
TABLE_NAME COMMENTS
------------------------------ --------------------------------------------------
USER_CONS_COLUMNS Information about accessible columns in constraint
definitions
ALL_CONS_COLUMNS Information about accessible columns in constraint
definitions
DBA_CONS_COLUMNS Information about accessible columns in constraint
definitions
<snip>

There is no complete answer. How would the database know of code that is outside of the database? It can't. So if you have a sql script, or some application that does not rely on stored procedures to do everything, the database will not know of them.
That said, for dependencies that are in stored procedures in the database, you can try this:
select *
from dba_dependencies
where referenced_link_name is not null
;

To add to the other (correct) answers that have been posted by #Littlefoot and #EdStevens, a quick-and-dirty analysis can also be made against the Automated Workload Repository (AWR).
The benefit of this approach is it will find usages of remote objects from SQL submitted to the database whether that SQL is in DBA_SOURCE or not (e.g., is embedded in an external application).
-- Find any objects referenced across a database link (sort of)
select object_node, object_name, count(distinct sql_id) sql_id_count
from dba_hist_sql_plan
where object_type = 'REMOTE'
group by object_node, object_name
order by object_node, object_name
;
The problem is that AWR data isn't 100% complete. First of all, it's not kept around forever, so a database link last used more than a month (or two months or however long your DBAs keep AWR data for) wouldn't be seen. Second of all, AWR only takes snapshots periodically, say every hour. So it's theoretically possible for a SQL to use a database link and then get aged out of the library cache before the next AWR snapshot.
I think the chance of missing something due to that last bit is small on the systems I work with. But, if you have poorly written applications (i.e., no bind variables) and limited shared pool space, it's something to worry about.

Related

How to find the columns used in a stored procedure

Is it possible to get a list of used columns in a particular procedure using PL/SQL? I have to check over 500 procedures in my Oracle DB and print out all the columns used in them.
Surprisingly, Oracle does make the calculated table dependencies in PL/SQL available for viewing:
select * from user_dependencies -- can also use all_ or dba_dependencies
where type = 'PROCEDURE' and REFERENCED_TYPE = 'TABLE';
But if you really need column-level dependencies, I think it'll be much more difficult. Here's a very simple answer that'll illustrate some of the problems with the question.
select name, type, line, text, table_name, column_name
from user_source
join user_tab_cols
on text like '%'|| column_name || '%';
So you can search through all your procedures for any strings that match an existing column name. I can think of dozens of problems with this approach; the commenters above mentioned some of them, like how deep into the call stack you want to look. Or depending on how your columns are named, ambiguous names (SID, MODIFIED_DATE, etc) will produce duplicate entries. And there's no way to distinguish between actual references to column names and local variables which happen to have the same spelling. Or comments. And views or synonyms can screw up your searching. It seems like a really tough question. I hope the tables from user_dependencies will be enough for your needs.

Which is better for returning resultset from an oracle database => Ref. Cursor vs Select sql statement

I have been googling for a while to find an alternative approach for returning a resultset rather than returning a ref cursor but failed to find it so. As i have done most of my development in sql server where we won't use cursors unless until it is necessary but i understand it differs from ref. cursor. But on top of that when we return a ref. cursor as an output from database it will become a connected architecture. So my dear Geeks can you answer/clear my confusions as mentioned below,
I want to understand which is the better way for returning a result set to our application (Ref. cursor or SELECT statement with all the joins or any other options)?
Is using ref. cursor is a connected /disconnected architecture?
Is using Select sql query is better for a disconnected approach?
Thanks in advance.
As usual, it depends on your needs.
Regarding connected /disconnected architecture it makes almost no difference. After your client application received the RefCursor and all rows are fetched (and preferably the cursor is closed) you can disconnect and reconnect from database the same way as using direct SELECT statement.
Consider following pseudo-code examples:
SELECT EMP_NAME, DEPT_NAME
FROM EMP
JOIN DEPT ON EMP_DEPT_ID = DEPT_ID
WHERE DEPT_ID = :d;
vs.
CREATE FUNCTION GetEmps(deptId IN NUMBER) RETURN SYS_REFCURSOR IS
res SYS_REFCURSOR;
BEGIN
OPEN res FOR
SELECT EMP_NAME, DEPT_NAME
FROM EMP
JOIN DEPT ON EMP_DEPT_ID = DEPT_ID
WHERE DEPT_ID = deptId;
RETURN res;
END;
My personal favorite is to prefer a RefCursors because:
With RefCursor client and server are more separated from each other, i.e. the client just has to know the function name and which attributes he receives (EMP_NAMEand DEPT_NAME), nothing else. He does not have to know the table names or any join condition. Developers of client and server can work more independently from each other.
With RefCursor you can implement fine-granularity security methods. You only have to do grant execute on GetEmps to ... and the client gets EMP_NAME and DEPT_NAME - no more, no less!
With direct SELECT you have to grant select on both tables, however then the client could also execute SELECT SALARY, EMP_NAME FROM EMP; for instance (unless you use the quite expensive VPD feature from Oracle). If you like you can log every single call of the function and add as many constraints as you like.
with RefCursor the client application (and not the server) can decide how many rows he like to fetch in order to optimize response times.
the basic difference is that when you are uncertain about the sql query you are going to execute at run time, then use ref cursor and you can use same ref cursor for different sql queries. for example
for query
select name,id,dob from table where id=:v_id;
here v_id is passed at run time, so we can use ref cursor. v_id varies at run time.
While the select statement is used in for each loop when we have small set of records. When we have large set of records we can use bulk collect with ref cursor and limit rows.
In Oracle, all DML statements are cursors. A cursor is simply a set of instructions used by the optimizer to get to the data.
In my Oracle-centric opinion, everything that is done in the database should be done in stored procedures, so that you have a central interface into the database - ie. if you had two applications updating/retrieving data to/from the same database, you'd only need one set of stored procs on the database, rather than replicating the logic twice in each application.
With that in mind, ref cursors are the way to go.
However, if you're not going down that route (boo! *{;-) ) there is little difference between a ref cursor and a straight select statement in terms of getting the data to the front end. How you call for the data will be different, of course, but it's the same thing to the database.
All a ref cursor does is basically hold a pointer to a cursor.

Finding Oracle stored procedures

Since I am new to Oracle, please tell me what different ways to find packages, stored procedures, triggers, functions, indexes, tablespaces
Thanks
The following statement gives you an overview of all database objects in the current user:
SELECT
object_name,
object_type
FROM
user_objects;
If you are searching for documentation, you can look at Morgan's Library
You can download Oracle SQL Developer free. This allows you to explore all the objects in your database via a simple interface.
I shall walk you through the different shades of "all_object":
SQL> show user
USER is "C##SCOTT"
SQL>
Getting all the types of object:
select distinct object_type from all_objects;
EDITION
CONSUMER GROUP
SEQUENCE
SCHEDULE
PROCEDURE
OPERATOR
DESTINATION
WINDOW
SCHEDULER GROUP
PACKAGE
PROGRAM
LOB
XML SCHEMA
JAVA RESOURCE
JOB CLASS
DIRECTORY
TABLE
SYNONYM
INDEX
VIEW
FUNCTION
INDEXTYPE
JAVA CLASS
TYPE
EVALUATION CONTEXT
25 rows selected.
Now, you can zoom down to the "TABLE" type of object:
select object_name||','||object_id||','||owner from all_objects where object_type='TABLE' ;
Or all the objects of an owner:
select object_name||','||object_id||','||OBJECT_TYPE from all_objects where owner = 'SYS';
Trust me, you will learn more this way - anyone can click through any GUI tool, but to issue the SQL command, you will need some knowledge.

Oracle PL/SQL: Retrieve list of permissioned procedures for account

I've researched here and elsewhere but haven't found an answer for the following.
I'd like to get a list of all procedures available to my application's Oracle account (AFAIK they're part of one package), and have tried the following command in sqlplus:
SELECT * from user_procedures;
However this only returns one row/procedure, when in fact the app has probably 20+ procedures it calls (successfully) on a regular basis. I can just look through the source code and extract all the stored procedure names, but I'd like to use the above and see it working, and as a basis for further examination of the db to assist in debugging (instead of always needing to run the app or write test client code, for example).
Does the above statement only return procedures my account owns explicitly, or should it show anything the account has access to? [I'm not very familiar with Oracle's specific features.]
I've tried other variations; for example, referencing 'dba_procedures' results in a 'table or view does not exist error.'
Are all of these symptoms the result of limited permissions on my app's Oracle account (which I'm using to connect via sqlplus)?
[Background: Dysfunctional environment--direct access to the DBMS and its external owners is extremely limited, so I'd like to be able to increase my understanding of the db design and get the information I need without assistance.]
You can see which stand-alone procedure you can execute with this:
select ao.object_type, ao.owner ||'.'|| ao.object_name
from all_objects ao, user_tab_privs utp
where ao.object_type = 'PROCEDURE'
and utp.owner = ao.owner
and utp.table_name = ao.object_name
and utp.privilege = 'EXECUTE';
But if they are in a package you can't directly see the procedure names, AFAIK, but you can see which package you can execute with this:
select ao.object_type, ao.owner ||'.'|| ao.object_name
from all_objects ao, user_tab_privs utp
where ao.object_type = 'PACKAGE'
and utp.owner = ao.owner
and utp.table_name = ao.object_name
and utp.privilege = 'EXECUTE';
And then you can desc[ribe] the package to see the individual procedures and functions within it. I guess that is probably held somewhere in the data dictionary but don't knwo where off-hand...
user_procedures is a system view that holds all the procedures owned by certain schema (user). Not the ones that the schema (user) is granted to execute.
You can try DBMS_METADATA.GET_GRANTED_DDL stored procedure. You might find something useful there. But I don't know what kind of privileges you need to run it within your application.
Hope it helps.
If the procedures are part of a package (i.e. you're calling them by PACKNAME.PROCNAME, then you have an all-or-nothing grant on the package, not individual procedures within the package.

Oracle 9i: Synonymed Table Does Not Exist?

I've created a package that contains a stored procedure that I plan to invoke from a separate application. The stored procedure will return a sorted list of all the views and tables in the schema. To do that, it performs a simple select on the DBA_TABLES and DBA_VIEWS synonyms, as shown below:
CREATE OR REPLACE
PACKAGE BODY TITAN_ENTITY AS
PROCEDURE GETSCHEMAOBJECTS (RESULTS IN OUT T_CURSOR)
IS
V_CURSOR T_CURSOR;
BEGIN
OPEN V_CURSOR FOR
SELECT 'T' OBJECTTYPE, TABLE_NAME OBJECTNAME
FROM DBA_TABLES
WHERE OWNER = 'SONAR5'
UNION ALL
SELECT 'V' OBJECTTYPE, VIEW_NAME OBJECTNAME
FROM DBA_VIEWS
WHERE OWNER = 'SONAR5'
ORDER BY OBJECTNAME;
RESULTS := V_CURSOR;
END GETSCHEMAOBJECTS;
END TITAN_ENTITY;
I have verified that the synonyms in question exist, and are public:
CREATE PUBLIC SYNONYM "DBA_TABLES" FOR "SYS"."DBA_TABLES"
CREATE PUBLIC SYNONYM "DBA_VIEWS" FOR "SYS"."DBA_VIEWS"
My understanding is that, because they are public, I don't need any further permissions to get to them. If that understanding is incorrect, I wish someone would disabuse me of the notion and point me to more accurate data.
Now here's my problem: I can open a worksheet in Oracle SQL Developer and select from these tables just fine. I get meaningful data just fine (567 rows, as a matter of fact). But when I try to execute the stored procedure, Oracle complains with a compilation error, as shown below:
Error(9,8): PL/SQL: SQL Statement ignored
Error(10,16): PL/SQL: ORA-00942: table or view does not exist
When I double-click on that second error message, SQL Developer takes me to the first FROM clause ("FROM DBA_TABLES").
So I'm fairly stumped. I know SQL Server pretty well, and I'm new to Oracle, so please bear with me. If you could provide some clues, or point me in the right direction, I'd really appreciate it.
Thanks in advance!
Use ALL_TABLES and ALL_VIEWS instead of DBA_TABLES and DBA_VIEWS. ALL_% views should be accessible to all users.
If you select from a table or a view in a stored PL/SQL-procedure or a stored PL/SQL-function you need a direct grant. A grant via a database role isn't enough.
You probably need a direct grant on view dba_tables. (public) synonyms are just (public) synonyms. You need directly granted select rights.
See here: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:48704116042682#48798240264807
Edit: Sorry, I glossed over the part where you seem to say that you can select from DBA_TABLES directly. Most likely the issue is that your privileges are granted through a role as someone else answered. But it's still worth explaining that your understanding of PUBLIC synonyms is incomplete, and that using ALL_TABLES would be better if it accomplishes what you need.
The synonym being PUBLIC only means that all users can reference the synonym; it does not grant them any access to the object that the synonym refers to.
What you would do to most directly solve this error is grant SELECT privilege on the SYS views to the user(s) that will run this procedure. However, I think that is a very bad idea.
As suggested by Raimonds, consider whether you can get what you need from USER_TABLES or ALL_TABLES instead. What user is calling this procedure, and what access does that user have to SONAR5's tables?
Generally, if your application is interested in a table, presumably it has some privileges on it, in which case is should be listed in ALL_TABLES.

Resources