Describe in SQL*Plus - does it call a package or run SQL? (Or something else?) - oracle

When I describe an Oracle TYPE in SQL*Plus, what does SQL*Plus do "under the bonnet" - Is it calling DBMS_METADATA (or similar)? Or is it querying the data dictionary directly?
Or something else entirely?

You can obviously use alter session set sql_trace=true to answer such questions.
For
create type desc_type as object (
dummy varchar2(1),
constructor function desc_type (a number) return self as result,
final member procedure m
);
/
alter session set sql_trace=true;
desc desc_type
alter session set sql_trace=false;
drop type desc_type
/
I find the following relevant SQL Statements in my trace file:
select procedure#,procedurename,properties,itypeobj#
from procedureinfo$ where obj#=:1
order by procedurename desc, overload# desc
select position#,
sequence#,
level#,
argument,
type#,
charsetid,
charsetform,
properties,
nvl(length, 0),
nvl(precision#, 0),
nvl(scale, 0),
nvl(radix, 0),
type_owner,
type_name,
type_subname,
type_linkname,
pls_type
from argument$
where obj#=:1 and procedure#=:2 order by sequence# desc
select max(procedure#) from procedurec$ where obj#=:1
select max(procedure#) from procedureplsql$ where obj#=:1
select max(procedure#) from procedurejava$ where obj#=:1
select procedure#,entrypoint# from procedurec$
where obj#=:1 order by procedure#
select procedure#,entrypoint#
from procedureplsql$ where obj#=:1 order by procedure#
select procedure#,ownerlength,classlength,methodlength,siglength, flagslength,cookiesize
from procedurejava$ where obj#=:1 order by procedure#
select ownername,classname,methodname,signature,flags
from procedurejava$ where obj#=:1 and procedure#=:2 order by procedure#
select count(*)
from vtable$ where obj#=:1
select vindex,itypetoid,imethod#,iflags,itypeowner,itypename
from vtable$ where obj#=:1 order by vindex
select externtype, externname
from type$ where tvoid=:1
So, under the bonnet, SQL*Plus uses plain SQL.

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;

how to store the result of a set operation into a variable

i tried it this way
set #v1 := (SELECT SUBSTR(IFSC,1,4) FROM rtgs_new MINUS SELECT SUBSTR(IFSC,1,4) FROM rtgs_temp);
or
set #v1 = (SELECT SUBSTR(IFSC,1,4) FROM rtgs_new MINUS SELECT SUBSTR(IFSC,1,4) FROM rtgs_temp);
but i get this error:
SP2-0158: unknown SET option "#v1"
i want to use this variable to compare with and insert into another oracle table.
any information will be helpful.
thank you guys!
If you just need to insert into another table, why don't you do that?
insert into another_table
SELECT SUBSTR(IFSC,1,4) FROM rtgs_new MINUS SELECT SUBSTR(IFSC,1,4) FROM rtgs_temp;

Finding sequences and triggers associated with an Oracle table

I have used this query to fetch the list of sequences belonging to an Oracle database user:
SELECT * FROM all_sequences x,all_tables B
WHERE x.sequence_owner=B.owner AND B.TABLE_NAME='my_table';
But that database user is having many more sequence also, so the query returns me all the sequence of the database user. Can anybody help me to find the particular sequence of my_table using query so that I can get the auto increment id in my application.
i want the query which fetch list of table of my database user with the sequence and triggers used in the table
You can get the triggers associated with your tables from the user_triggers view. You can then look for any dependencies recorded for those triggers in user_dependencies, which may include objects other than sequences (packages etc.), so joining those dependencies to the user_sequences view will only show you the ones you are interested in.
Something like this, assuming you are looking at your own schema, and you're only interesting in triggers that references sequences (which aren't necessarily doing 'auto increment', but are likely to be):
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from user_tables tabs
join user_triggers trigs
on trigs.table_name = tabs.table_name
join user_dependencies deps
on deps.name = trigs.trigger_name
join user_sequences seqs
on seqs.sequence_name = deps.referenced_name;
SQL Fiddle demo.
If you're actually looking at a different schema then you'll need to use all_tables etc. and filter and join on the owner column for the user you're looking for. And if you want to include tables which don't have triggers, or triggers which don't refer to sequences, you can use outer joins.
Version looking for a different schema, though this assumes you have the privs necessary to access the data dictionary information - that the tables etc. are visible to you, which they may not be:
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from all_tables tabs
join all_triggers trigs
on trigs.table_owner = tabs.owner
and trigs.table_name = tabs.table_name
join all_dependencies deps
on deps.owner = trigs.owner
and deps.name = trigs.trigger_name
join all_sequences seqs
on seqs.sequence_owner = deps.referenced_owner
and seqs.sequence_name = deps.referenced_name
where tabs.owner = '<owner>';
If that can't see them then you might need to look at the DBA views, again if you have sufficient privs:
select tabs.table_name,
trigs.trigger_name,
seqs.sequence_name
from dba_tables tabs
join dba_triggers trigs
on trigs.table_owner = tabs.owner
and trigs.table_name = tabs.table_name
join dba_dependencies deps
on deps.owner = trigs.owner
and deps.name = trigs.trigger_name
join dba_sequences seqs
on seqs.sequence_owner = deps.referenced_owner
and seqs.sequence_name = deps.referenced_name
where tabs.owner = '<owner>';
One way would be to run these queries to check if there are any sequence's Pseudocolumns (NEXTVAL and CURRVAL ) used in your functions , procedures, packages, Triggers or PL/SQL JAVA SOURCE.
select * from user_source where
UPPER(TEXT) LIKE '%NEXTVAL%';
select * from all_source where
UPPER(TEXT) LIKE '%NEXTVAL%';
Then go to the specific Procedure, Function or Trigger to check which column/table gets populated by a sequence.
The query could also be used with '%CURRVAL%'
This might not help if you are running inserts from JDBC or other external applications using a sequence.
Oracle 12c introduced the IDENTITY columns, using which you could create a table with an identity column, which is generated by default.
CREATE TABLE t1 (c1 NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
c2 VARCHAR2(10));
This will internally create a sequence that auto-generates the value for the table's column.So, If you would like to know which sequence generates the value for which table, you may query the all_tab_columns
SELECT data_default AS sequence_val
,table_name
,column_name
FROM all_tab_columns
WHERE OWNER = 'HR'
AND identity_column = 'YES';
SEQUENCE_VAL |TABLE_NAME |COLUMN_NAME
-----------------------------------------|-------------------------------------
"HR"."ISEQ$$_78160".nextval |T1 |C1
I found a solution to this problem to guess the sequence of a particular sequence
select * from SYS.ALL_SEQUENCES where SEQUENCE_OWNER='OWNER_NAME' and LAST_NUMBER between (select max(FIELD_NAME) from TABLE_NAME) and (select max(FIELD_NAME)+40 from TABLE_NAME);
This query will guess by search the LAST_NUMBER of the sequence value between MAX value of the field using sequence and Max value + 40 (in my case cache value is 20, so I put 40)
select SEQUENCE_NAME from sys.ALL_TAB_IDENTITY_COLS where owner = 'SCHEMA_NAME' and table_name = 'TABLE_NAME';

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;

Query Oracle for running sql and value of bind variables

If I run the SQL in Fig. 1 below, it may return something like this:
Select fname, lname from name_tbl where nam_key = :key
Without using some fancy DBA trace utility, how can I query an Oracle system table to find the value of the bind variable “:key”?
Figure 1. - List the current running sql statement.
select sid, username, sql_text
from v$session,
v$sqltext
where sql_address = address
and sql_hash_value = hash_value
order by sid, piece;
select name, value_string
from v$sql_bind_capture
where sql_id = your_query_id
Upd. or, of course:
select sql_id, value_string
from v$sql_bind_capture
where name = ':key'

Resources