getting the currently logged on user and the number of valid stored procedure in sql - oracle

I would like to find out if its possible to get the number of valid and invalid stored procedures in SQL. Also the currently logged on user and the current time

To get the invalid objects use
SELECT *
FROM dba_objects
WHERE object_type IN ('PACKAGE'
, 'PACKAGE BODY'
, 'PROCEDURE'
, 'FUNCTION')
AND status <> 'VALID';
OR
SELECT STATUS, COUNT(*)
FROM dba_objects
WHERE object_type IN ('PACKAGE'
, 'PACKAGE BODY'
, 'PROCEDURE'
, 'FUNCTION')
GROUP BY status
for just a count of the statuses.
You might need to tweak the list of object types depending on what you want and you may want to limit it by OWNER as well.
The following shows the current time and a few methods of getting the user (schema, OS and the user from 'client identifier').
I suggest you try it and see which one you actually want and/or have populated.
SELECT TO_CHAR(SYSDATE, 'HH24:MI:SS') AS current_NLS
, TO_CHAR(SYS_EXTRACT_UTC(SYSTIMESTAMP),'HH24:MI:SS') AS UTC_TIME
, USER
, SYS_CONTEXT('USERENV', 'OS_USER')
, REGEXP_SUBSTR(SYS_CONTEXT('userenv', 'client_identifier'), '^[^:]*')
FROM DUAL;

Related

Count of rows from all views in Oracle with a condition

I am trying to get count of all rows from views in oracle schema and my code is working fine. But when i try to add a condition like where actv_ind = 'Y', i am unable to get it working. Any suggestions on how to modify the code to make it working?
SELECT view_name,
TO_NUMBER(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) cnt from '||owner||'.'||view_name||
'where'||view_name||'.'||'actv_ind= Y')),'/ROWSET/ROW/CNT')) as VIEW_CNT
FROM all_views
WHERE owner = 'ABC' AND view_name not in ('LINK$')
I am getting the error ACTV_IND : Invalid Identifier.
The error messages from DBMS_XMLGEN are not very helpful so you need to be very careful with the syntax of the SQL statement. Add a space before and after the where, and add quotation marks around the Y:
SELECT view_name,
TO_NUMBER(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) cnt from '||owner||'.'||view_name||
' where '||view_name||'.'||'actv_ind= ''Y''')),'/ROWSET/ROW/CNT')) as VIEW_CNT
FROM all_views
WHERE owner = 'ABC' AND view_name not in ('LINK$');
The query still assumes that every view contains the column ACTV_IND. If that is not true, you might want to base the query off of DBA_TAB_COLUMNS WHERE COLUMN_NAME = 'ACTV_IND'.
Here's a simple sample schema I used for testing:
create user abc identified by abc;
create or replace view abc.view1 as select 1 id, 'Y' actv_ind from dual;
create or replace view abc.view2 as select 2 id, 'N' actv_ind from dual;

varchar in execute immediate

I'm using the following script pl/sql:
EXECUTE IMMEDIATE 'insert into TAB1(ID, CODE, TYPE, ORDRE)
select ''KEY'', ''KEY_LIB'', ''TYP_KEY'', 3 FROM dual
where not exists(
select ID,CODE,TYPE,ORDRE
FROM TAB1
where TYPE=''TYP_KEY''
AND CODE =''KEY_LIB''
)';
And I'm getting the following error :
00000 - "FROM keyword not found where expected
The error seems to be in the second line but I can't figure out what's wrong.
Can anyone help please ?
Type is a keyword in Oracle. So, try with tablename.Type when type is a column name. Here is your revised query:
EXECUTE IMMEDIATE 'insert into TAB1(ID, CODE, TYPE, ORDRE)
select ''KEY'', ''KEY_LIB'', ''TYP_KEY'', 3 FROM dual
where not exists(
select ID,CODE,TYPE,ORDRE
FROM TAB1
where TAB1.TYPE=''TYP_KEY''
AND CODE =''KEY_LIB''
)';
You should better try it like this:
EXECUTE IMMEDIATE 'insert into TAB1(ID, CODE, "TYPE", ORDRE)
select :KEY, :KEY_LIB, :TYP_KEY, 3 FROM dual
where not exists(
select ID,CODE,"TYPE",ORDRE
FROM TAB1
where "TYPE" = :TYP_KEY
AND CODE = :KEY_LIB
)'
USING 'KEY', 'KEY_LIB', 'TYP_KEY', 'TYP_KEY', 'KEY_LIB';
You can use Alternative Quoting Mechanism (''Q'') for String Literals, then you don't need double quotes. With this technique it is much easier to test queries manually (if it is needed). Btw, your query works fine.
BEGIN
EXECUTE IMMEDIATE
q'[INSERT INTO tab1(id, code, type, ordre)
SELECT 'KEY', 'KEY_LIB', 'TYP_KEY', 3
FROM dual
WHERE NOT EXISTS(
SELECT 1
FROM tab1
where tab1.type = 'TYP_KEY'
AND code = 'KEY_LIB'
)]';
END;
/

How do I differentiate between Procedures and Functions in Oracle's Metadata?

I want to list all the Stored Procedures which use overloading in a given schema. All the procedures are within packages. I can use the SQL below to nearly get there (anything with proc_count > 1).
select
object_name, procedure_name, count(procedure_name) as proc_count
from
all_procedures
where
owner = 'SCHEMA_NAME'
group by
object_name, procedure_name
order by proc_count desc
However there seems to be no way to differentiate between a function named 'ask_version' and a procedure named 'ask_version' which I need to do in my case. The case being that our middleware has trouble calling procs where overloading is used. I need to do an impact analysis on how many places this occurs. We never call functions directly, hence the need to isolate them
Is there something that I'm missing?
all_arguments seems to help. For a function, there is an argument with position=0 (which is the return value), for procedures this argument does not exist.
SELECT object_name, procedure_name, t, COUNT(1) AS proc_count
FROM
(
SELECT p.object_name, p.procedure_name,
CASE WHEN a.object_id IS NULL THEN 'PROCEDURE' ELSE 'FUNCTION' END AS t
FROM all_procedures p
LEFT JOIN all_arguments a ON ( a.object_id = p.object_id
AND a.subprogram_id = p.subprogram_id AND a.position = 0 )
WHERE p.owner = 'SCHEMA_NAME'
)
GROUP BY object_name, procedure_name, t
ORDER BY proc_count DESC;
This is a bit tricky since Oracle stores packages as discrete objects from standalone functions and procedures.
The only easy way you can tell this is by looking at the argument metadata in ALL_ARGUMENTS. Functions have an argument at position 0 to specify the return type, whereas procedures do not.
Also, it's easy to tell if a function or procedure has overloads by checking the OVERLOAD field.
select P.OBJECT_NAME
, P.PROCEDURE_NAME
, DECODE(min(a.POSITION), 0, 'Function', 'Procedure') FUNC_OR_PROC
, DECODE(NVL(min(P.OVERLOAD), 0), 0, 'No', 'Yes') OVERLOADED
from ALL_PROCEDURES P
, ALL_ARGUMENTS a
where P.OWNER = 'FLOWS_030000'
and P.OBJECT_NAME = a.PACKAGE_NAME
and P.PROCEDURE_NAME = a.OBJECT_NAME
group by P.OBJECT_NAME, P.PROCEDURE_NAME
order by 1,2;

Native method to pull out metadata about packages, procedures and functions?

I wish to be able to query Oracle for a list of public procedures and functions that belong to a package, something along the lines of:
select procedure_name from all_package_procedures where package_name = :my_package_name;
I also wish to be able to query Oracle for a list of parameters for a given procedure or function, something along the lines of:
select parameter_name, in_or_out, parameter_type from all_function_parameters where function_name = :my_function_name;
Is this possible natively? If not, does anyone know of existing code to achieve this?
You can query USER_OBJECTS & USER_PROCEDURES to get a list of all procedures & functions belonging to a particular package
SELECT procedure_name
FROM user_procedures
WHERE object_id = (SELECT object_id
FROM user_objects
WHERE object_name = '<YOUR-PACKAGE-NAME>'
AND object_type = 'PACKAGE')
Replace user_objects & user_procedures with all_objects & all_procedures respectively to fetch packages & procedures owned by other users.
I also wish to be able to query Oracle for a list of parameters for a given procedure or function,
For this, you can query user_arguments or all_arguments to fetch parameters of on object owned by the current user & all users respectively
SELECT argument_name,
data_type
FROM user_arguments
WHERE package_name = '<name-of-your-package-procedure-function>'
My own answer, derived from Sathyas, for the reference of others. Here is a single query to pull out a denormalized result of all procedures and their arguments for a given package:
select p.procedure_name
, a.argument_name
, a.data_type
, a.defaulted
, a.default_value
, a.in_out
, a.position
from all_procedures p
inner join all_objects o
on o.object_id = p.object_id
inner join all_arguments a
on a.package_name = o.object_name
and a.object_name = p.procedure_name
where o.object_type = 'PACKAGE'
and o.object_name = 'PACKAGE_NAME'
order by p.procedure_name, a.position;

Binding variables in dynamic PL/SQL

I have a dynamic PL/SQL that will construct the SELECT statement based on what the searching criteria input from the users,likes:
l_sql := 'SELECT * INTO FROM TABLEA WHERE 1=1 ';
IF in_param1 IS NOT NULL THEN
l_sql := l_sql || 'AND column1 = in_param1 ';
END IF;
IF in_param2 IS NOT NULL THEN
l_sql := l_sql || 'AND column2 = in_param2 ';
END IF;
...................................
IF in_paramXX IS NOT NULL THEN
l_sql := l_sql || 'AND columnXX = in_paramXX ';
END IF;
To reduce the hard parse overhead , I consider to use the binding variables. However , it is difficult to manage when supplying the actual values to the binding variables as there are so many binding variables and combination of the generated SELECT statement . I cannot use the method of DBMS_SESSION.set_context() introduced at http://www.dba-oracle.com/plsql/t_plsql_dynamic_binds.htm because my account has no right to use this package. Besides , I want the generated SQL only contains the conditions on the fields that the user did not leave empty. So I cannot change the dynamic SQL to something likes
SELECT * INTO FROM TABLEA WHERE 1=1
and ( in_param1 is NULL or column1 = in_param1)
and ( in_param2 is NULL or column2 = in_param2)
...............................................
and ( in_paramXX is NULL or columnXX = in_paramXX)
So , I want to try to use the DBMS_SQL method .Can anyone give an example about how to use DBMS_SQL to call dynamic SQL with binding variables? Especially , how can I get the result executed from DBMS_SQL.execute() to the SYS_REFCURSOR , something like :
open refcursor for select .... from
The oracle version that I use is 10g and it seems that the oracle 10g does not have DBMS_Sql.To_Refcursor()
In your Oracle version you can apply some tricks to your query in order to do this. The idea is to use a query in the following form:
select *
from
(select
:possibleParam1 as param1
-- do the same for every possible param in your query
:possibleParamN as paramN
from dual
where rownum > 0) params
inner join
-- join your tables here
on
-- concatenate your filters here
where
-- fixed conditions
then execute it with:
open c for query using param1, ..., paramN;
It works by using DUAL to generate a fake row with every single param, then inner joining this fake row to your real query (without any filters) using only the filters you want to apply. This way, you have a fixed list of bind variables in the SELECT list of the params subquery, but can control which filters are applied by modifying the join condition between params and your real query.
So, if you have something like, say:
create table people (
first_name varchar2(20)
last_name varchar2(20)
);
you can construct the following query if you just want to filter on first name
select *
from
(select
:first_name as first_name,
:last_name as last_name
from dual
where rownum > 0) params
inner join
people
on
people.first_name = params.first_name;
and this if you want to filter on both first_name and last_name
select *
from
(select
:first_name as first_name,
:last_name as last_name
from dual
where rownum > 0) params
inner join
people
on
people.first_name = params.first_name and
people.last_name = params.last_name;
and in every case you would execute with
open c for query using filterFirstName, filterLastName;
It is important for performance to use the where rownum > 0 with DUAL as it forces Oracle to "materialize" the subquery. This usually makes DUAL stop interfering with the rest of the query. Anyway, you should check the execution plans to be sure Oracle is not doing anything wrong.
In 10g a DBMS_SQL cursor can't be changed into a Ref Cursor. Going through a result set through DBMS_SQL is tortuous since, as well as looping through the rows, you also have to loop through the columns in a row.
I want the generated SQL only contains
the conditions on the fields that the
user did not leave empty
Is that purely for performance reasons ? If so, I suggest you work out what the practical execution plans are and use separate queries for them.
For example, say I'm searching on people and the parameters are first_name, last_name. gender, date_of_birth. The table has indexes on (last_name,first_name) and (date_of_birth), so I only want to allow a query if it specifies either last_name or date_of_birth.
IF :p_firstname IS NOT NULL and :p_lastname IS NOT NULL THEN
OPEN cur FOR
'SELECT * FROM PEOPLE WHERE last_name=:a AND first_name=:b AND
(date_of_birth = :c or :c is NULL) AND (gender = :d or :d IS NULL)' USING ....
ELSIF :p_lastname IS NOT NULL THEN
OPEN cur FOR
'SELECT * FROM PEOPLE WHERE last_name=:a AND
(date_of_birth = :c or :c is NULL) AND (gender = :d or :d IS NULL)' USING ....
ELSIF :p_dateofbirth IS NOT NULL THEN
OPEN cur FOR
'SELECT * FROM PEOPLE WHERE date_of_birth=:a AND
(first_name=:b OR :b IS NULL) AND (gender = :d or :d IS NULL)' USING ....
ELSE
RAISE_APPLICATION_ERROR(-20001,'Last Name or Date of Birth MUST be supplied);
END IF;

Resources