Plsql Subprograms:
A
subprogram is a named block of PL/SQL.
There
are two types of subprograms in PL/SQL namely Procedures and Functions.
Every
subprogram will have a declarative part, an executable part or body, and an
exception handling part, which is optional.
A procedure may or
may not return any value.
A stored procedure, function, or package is a PL/SQL program unit that:
- Has a name. A subprogram
is a named block of PL/SQL.
- Can take
parameters, and can return values.
- Is stored in the
data dictionary.
- Can be called by
many users.
Note:
The term stored
procedure is sometimes used generically for both stored procedures and
stored functions.
The only difference between procedures and functions is that functions
always return a single value to the caller, while procedures do not return a
value to the caller.
Naming Procedures and Functions :
Because a procedure or function is stored in the database, it must be
named.
This distinguishes it from other stored procedures and makes it possible
for applications to call it.
Each publicly-visible procedure or function in a schema must have a unique
name, and the name must be a legal PL/SQL identifier.
Note:
If you plan to call a stored procedure using a stub generated by
SQL*Module, then the stored procedure name must also be a legal identifier in
the calling host 3GL language, such as Ada
or C.
Your software checklist:
- A text editor. The code examples were
written with Microsoft ® Notepad version 5.1, supplied with the operating
system called Microsoft ® Windows XP Professional.
- A tool to submit Oracle SQL and PL/SQL
statements to an Oracle database. The code examples were tested in
Oracle's SQL*Plus tool, version 3.3.4.0.0 for Windows.
- An Oracle database you can connect to
with a user name and password. Your user name should be set up with the
permission to write procedures: the CREATE PROCEDURE
system privilege. The code examples were tested on an
Oracle9i database, version 9.2.0.
Creating Procedures:
In Oracle, you can create your own procedures.
CREATE [OR REPLACE] PROCEDURE
procedure_name
[ (parameter [,parameter]) ]
IS
[declaration_section]
BEGIN
executable_section
[EXCEPTION
exception_section]
END [procedure_name];
[ (parameter [,parameter]) ]
IS
[declaration_section]
BEGIN
executable_section
[EXCEPTION
exception_section]
END [procedure_name];
In
the above given syntax things enclosed in between angular brackets (“<
> “) are user defined
enclosed
in between square brackets (“[ ]”)
are optional.
AUTHID clause is
used to decide whether the procedure should execute with invoker (current-user
or person who executes it) or with definer (owner or person created) rights
When you create a procedure or function, you may define parameters.
There are three types of parameters that can be declared:- IN - The parameter can be referenced by the procedure or function.
The value of the parameter can not be
overwritten by the procedure or function.
- OUT - The parameter can not be referenced by the procedure or
function, but the value of the parameter can be
overwritten by the procedure or function.
- IN OUT - The parameter can be referenced by the procedure or function and
the value of the parameter can be overwritten
by the procedure or function.
PL/SQL procedures behave very much like procedures in other
programming language.
Here Is An Example Of A Pl /Sql
Procedure:
addtuple1 that,
given an integer i, inserts the tuple (i, 'xxx') into the following example
relation:
CREATE
TABLE T2 (
a INTEGER,
b CHAR(10)
);
CREATE PROCEDURE addtuple1(i IN NUMBER) AS
BEGIN
INSERT INTO T2 VALUES(i, 'xxx');
END addtuple1;
run;
Procedure is a subprogram used to perform a specific
action. A procedure contains two parts specification and the body.
Procedure specification begins with CREATE and ends with procedure
name or parameters list. Procedures that do not take parameters are written
without a parenthesis.
The body of the procedure starts after the keyword IS or AS and ends
with keyword END.
Explanation of every keyword in procedure:
CREATE [OR REPLACE] :
A procedure is introduced by the keywords CREATE PROCEDURE followed by the procedure name
and its parameters.
An option is to follow CREATE by OR REPLACE. The
advantage of doing so is that should you have already made the definition, you
will not get an error.
On the other hand, should the previous definition be a different
procedure of the same name, you will not be warned, and the old procedure will
be lost.
Q1: //why create
or replace why not drop and create
There
can be any number of parameters, each followed by a mode and a type.
The
possible modes are
IN (read-only),
An IN
parameter is used an input only. An IN parameter cannot be changed by the
called program.
OUT (write-only), and
An OUT parameter
is initially NULL. The program assigns the parameter a value and that
value is returned to the calling program.
INOUT (read and write).
An IN OUT parameter may or may not
have an initial value. That initial value may or may not be modified by the
called program. Any changes made to the parameter are returned to the calling
program.
Parameters are declared with data
types but without data type length or precision. That means that a
parameter may be declared as VARCHAR2 but it will not be declared with a length
component (VARCHAR2(30) would not be valid).
Note: Unlike
the type specifier in a PL/SQL variable declaration, the type specifier in a
parameter declaration must be unconstrained.
For
example, CHAR(10) and VARCHAR(20) are illegal; CHAR or VARCHAR should be used instead. The actual length of a parameter depends
on the corresponding argument that is passed in when the procedure is invoked.
Note that assigning values to parameters declared as OUT or INOUT causes the corresponding input arguments to be written.
Because
of this, the input argument for an OUT or INOUT parameter should be something with an
"lvalue", such as a variable like v in the example above.
A
constant or a literal argument should not be passed in for an OUT/INOUT parameter.
Parameters may also be assigned a
default value. You can either use the assignment operator (:=) or use the
DEFAULT keyword. When a parameter has a default value, you do not need to
include that parameter in the call. You MUST always include IN OUT and OUT
parameters.
( parameter_1 IN VARCHAR2 := 'ABC',
parameter_2 IN
VARCHAR2 DEFAULT 'ABC',
Q2: //why CHAR(10) and VARCHAR(20) are illegal and why we use CHAR or VARCHAR should be used instead
AS OR
IS :
Following
the arguments is the keyword AS (IS is a synonym).
Then
comes the body, which is essentially a PL/SQL block. We have repeated the name
of the procedure after the END, but
this is optional.
However,
the DECLARE
section should not start with the keyword DECLARE. Rather, following AS we have:
... AS
<local_var_declarations>
BEGIN
<procedure_body>
END;
RUN:
The run at the end runs the statement that creates
the procedure; it does not execute the
procedure.
NOTE: In the
examples given above, we are using backward slash ‘/’ at the end of the
program. This indicates the oracle engine that the PL/SQL program has ended and
it can begin processing the statements.
Actual Versus Formal Subprogram Parameters
Subprograms
pass information using parameters.
The variables or expressions referenced in the parameter list of a subprogram
call are actual
parameters. For example, the following procedure call lists two actual
parameters named
emp_num
and amount
:raise_salary(emp_num, amount);
raise_salary(emp_num, merit + cola);
The
variables declared in a subprogram spec and referenced in the subprogram body
are formal
parameters. For example, the following procedure declares two formal parameters
named
emp_id
and amount
:
PROCEDURE raise_salary (emp_id INTEGER, amount REAL) IS
BEGIN
UPDATE emp SET sal = sal + amount WHERE empno = emp_id;
END raise_salary;
When
you call procedure
raise_salary
, the actual
parameters are evaluated and the results are assigned to the corresponding
formal parameters.
If
necessary, before assigning the value of an actual parameter to a formal
parameter, PL/SQL converts the datatype of the value. For example, the
following call to
raise_salary
is valid:raise_salary(emp_num, '2500');
For
instance, PL/SQL cannot convert between the
DATE
and REAL
datatypes.
Also,
the result must be convertible to the new datatype. The following procedure
call raises the predefined exception
VALUE_ERROR
because PL/SQL cannot convert the second actual parameter to a
number:raise_salary(emp_num, '$2500'); -- note the dollar sign
Execution:
Positional Versus Named Notation for Subprogram Parameters:
When calling a subprogram, you can write
the actual parameters using either positional or named notation.
That is, you can indicate the association between an actual and
formal parameter by position or name. So, given the declarations
DECLARE
Using Positional Notation
The first procedure call uses positional notation.
The PL/SQL compiler associates the first actual parameter, acct,
with the first formal parameter, acct_no. And, the compiler associates the
second actual parameter, amt, with the second formal parameter, amount.
Using Named Notation
The second procedure call uses named notation. An arrow (=>)
serves as the association operator, which associates the formal parameter to
the left of the arrow with the actual parameter to the right of the arrow.
The third procedure call also uses named notation and shows that
you can list the parameter pairs in any order. So, you need not know the order
in which the formal parameters are listed.
Using Mixed Notation
The fourth procedure call shows that you can mix positional and
named notation. In this case, the first parameter uses positional notation, and
the second parameter uses named notation. Positional notation must precede
named notation. The reverse is not allowed. For example, the following
procedure call is illegal:
credit_acct(acct_no => acct, amt); -- illegal
To
execute the procedure, use another PL/SQL statement, in which the procedure is
invoked as an executable statement. For example:
General way of Execution :
BEGIN
addtuple1(99);
END;
run;
With Execute statement :
execute addtuple1(99);
With Exec Statement :
exec addtuple1(99);
The following procedure also inserts a tuple into T2, but it takes both components as
arguments:
Example Procedues which involves IN mode parameters::
Using the IN Mode
Inside the subprogram, an IN parameter acts like a
constant.
Therefore, it cannot be assigned a value.
Let’s
create a procedure which gets the name of the employee when the employee id is
passed.
1> CREATE OR REPLACE PROCEDURE emp_name (id IN
NUMBER, emp_name OUT NUMBER)
2> IS
3> BEGIN
4>
SELECT first_name INTO emp_name
5> FROM
emp_tbl WHERE empID = id;
6>dbms_output.put_line(‘the name of the employee
is ‘||emp_name);
7> END;
8> /
For
example, the following assignment statement causes a compilation error:
PROCEDURE debit_account (acct_id IN INTEGER, amount
IN REAL) IS
The
actual parameter that corresponds to an IN formal parameter can be a constant,
literal, initialized variable, or expression.
Unlike
OUT and IN OUT parameters, IN parameters can be initialized to default values.
For more information, see "Using
Default Values for Subprogram Parameters".
Execution of Procedues which involves IN mode parameters:
Examples:
Constant as
a actual parameter: exec tes(100);
Initialised
Variable as a actual parameter: exec tes(:acct);
Variable decaration:
var account_number number;
Exec : account_number :=40000000;
Procedure Execution: exec tes
(account_number);
Knowledge for variable declaration and initialization in sql * plus:
In SQL*Plus, a bind variable is declared
with variable:
After
the declaration, a value can be assigned to the variable
The
value of the bind variable can then be printed with print:
print num_var
Assigning value to the bind
variable:
Since an execute is basically a wrapper around
a begin .. end PL/SQL
block, a variable can be assigned a value like so:
Example illustrating out parameter:
The following illustrates the use of an OUT parameter:
CREATE TABLE T3 (
a INTEGER,
b INTEGER
);
CREATE PROCEDURE addtuple3(a NUMBER, b OUT NUMBER)
AS
BEGIN
b := 4; //out variable can be overwritten
INSERT INTO T3 VALUES(a, b);
END;
run;
DECLARE
v NUMBER;
BEGIN
addtuple3(10, v); //procedure call
END;
.
run;
Using Invoker's Rights Versus Definer's Rights (AUTHID Clause):
Oracle8i
Database introduced the AUTHID clause for procedures, functions and packages.
By default,stored procedures and SQL methods execute with
the privileges of their owner, not their current user.
Such definer's rights subprograms are bound to the schema
in which they reside, allowing you to refer to objects in the same schema
without qualifying their names.
When
set to AUTHID DEFINER (the default), then your program runs under
"definer rights." This means that any references to data objects
(such as tables and views) are resolved at compile time, based on the directly
granted privileges of the definer or owner of the program. Roles are ignored.
If,
on the other hand, you set the clause to AUTHID CURRENT_USER,
then any references to data objects are resolved at run time, based on the
privileges of the currently-connected schema. And (the DBAs have got to
love this) role-based privileges are now applied.
A
stored procedure runs either with the rights of the caller (authid
current_user) or with the rights of the procedure's owner (authid
definer). This behaviour is specified with the authid clause. This authid
clause immediatly follows the create procedure, create function, create package
or create type statement. It can be ommited, in which case the default authid definer is taken.
By default,stored procedures
and SQL methods execute with the privileges of their owner, not their current
user.Such definer's rights
subprograms are bound to the schema in which they reside, allowing you to refer
to objects in the same schema without qualifying their names. For example, if schemas
HR
and OE
both have a table called departments
, A procedure owned by
HR
can refer to departments
rather than HR.departments
. If user OE
calls HR
's procedure, the procedure
still accesses the departments
table owned by HR
.If you compile the same procedure in both schemas, you can define the schema name as a variable in SQL*Plus and refer to the table like
&schema..departments
. The code is portable, but if you change it, you must recompile it in each
schema.A more maintainable way is to use the
AUTHID
clause, which makes stored procedures and SQL
methods execute with the privileges and schema context of the calling user. You
can create one instance of the procedure, and many users can call it to access
their own data.Such invoker's rights subprograms are not bound to a particular schema. The following version of procedure
create_dept
executes with the privileges of the calling user and inserts rows into that
user's departments
table:
Example 8-13 Specifying Invoker's Rights With a
Procedure:
CREATE OR REPLACE PROCEDURE create_dept (
v_deptno NUMBER,
v_dname VARCHAR2,
v_mgr NUMBER,
v_loc NUMBER)
AUTHID CURRENT_USER AS
BEGIN
INSERT INTO departments VALUES (v_deptno, v_dname, v_mgr, v_loc);
END;
/
CALL create_dept(44, 'Information Technology', 200, 1700);
My Example
without AUTHID CURRENT_USER
CLAUSE:
Now I am connected
to the scott\tiger@upsssub66 account and
I create an procedure with emp table
create or replace procedure addename(empnumber number) is
begin
insert into emp columns(ename,empno) values('UPSS',empnumber);
end;
begin
insert into emp columns(ename,empno) values('UPSS',empnumber);
end;
SQL> /
Procedure createdSQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
SQL>
There is no rows in the emp table..
SQL> exec addename(125);
PL/SQL procedure successfully completed
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
125 UPSS
SQL>
Now I am login into the simulator/simulator@upsssub66
SIMULATOR>> SELECT * FROM EMP;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
there are no rows in the emp table
now I am executing the addename() procedure from simulator schema
SIMULATOR>> exec addename(145);
begin addename(145); end;
ORA-06550: line 1, column 7:
PLS-00201: identifier 'ADDENAME' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SIMULATOR>> exec scott.addename(145);
PL/SQL procedure successfully completed
SIMULATOR>> commit;
Commit complete
SIMULATOR>> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
SIMULATOR>>
Now I am connected to the scott\tiger@upsssub66 account
SQL> select * from emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
125 UPSS
145 UPSS
The table updated in scott schema table because of without AUTHID CURRENT_USER CLAUSE
My Example with
AUTHID CURRENT_USER CLAUSE:
Note: if you use AUTHID CURRENT_USER CLAUSE in your
procedure then the row inserted into emp table in the SIMULATOR SCHEMA Then the procedure with authid current_user clause
create or replace procedure addename(empnumber number)
authid current_user is
begin
insert into emp columns(ename,empno) values('UPSS',empnumber);
end;
Complete Demonstration About
Authid Clause:
The authid
clause has implications, for example, on how objects are resolved within a
procedure. This is demonstrated in the following. First, two users are created, one named a and one named b. Some needed privileges are granted to these users as well.
create user a identified by a default tablespace data quota unlimited on data;
create user b identified by b default tablespace data quota unlimited on data;
grant create session, create procedure, create table to a;
grant create session, create procedure, create table to b;
Now, user a creates tow tables named t and u and fills them with this is a's table. User u is allowed to read t.
connect a/a;
create table t (d varchar2(40));
insert into t values ('this is a''s table');
commit;
create table u (d varchar2(40));
insert into u values ('this is a''s table');
grant select on t to b;
-- no grant on u
User a also creates a procedure (named pt) with authid current_user that just reads what was filled into table t:
create procedure pt
authid current_user
as
v_d t.d%type;
begin
select d into v_d from t;
dbms_output.put_line(v_d);
end;
/
User a then creates a procedure (pu) that reads from table u:
create procedure pu
authid definer
as
v_d t.d%type;
begin
select d into v_d from u;
dbms_output.put_line(v_d);
end;
/
User b should be allowed to execute both procedures:
grant execute on pt to b;
grant execute on pu to b;
Now, it's user b's turn to do something. He, as well, creates two tables t and u and fills them with this is b's table:
connect b/b;
create table t (d varchar2(40));
insert into t values ('this is b''s table');
create table u (d varchar2(40));
insert into u values ('this is b''s table');
commit;
Now, he executes user a's procedure pt:
set serveroutput on
begin a.pt; end;
/
The output is:
this is b's table
Then, he executes a.pu:
begin a.pu; end;
/
This time, the output is:
this is a's table
This demonstrates that a procedure is run in the context of the caller if has authid current_user and in the context of the owner if the procedure has authid definer
Effects
on roles:
A
procedure with authid definer disables all roles
that are granted to the caller.This can lead to ora-00942 errors.
If the procedure is created with authid current_user, the roles of the caller are enabled when the procedure is executed. However, in order to compile the procedures, the privileges still need to be granted directly.
Advantages of Invoker's Rights:
Invoker's
rights subprograms let you reuse code and centralize application logic. They
are especially useful in applications that store data using identical tables in
different schemas. All the schemas in one instance can call procedures owned by a central schema. You can even have schemas in different instances call centralized procedures using a database link.
Consider a company that uses a stored procedure to analyze sales. If the company has several schemas, each with a similar
SALES
table, normally it would also need several copies
of the stored procedure, one in each schema.To solve the problem, the company installs an invoker's rights version of the stored procedure in a central schema. Now, all the other schemas can call the same procedure, which queries the appropriate to
SALES
table in each case.You can restrict access to sensitive data by calling from an invoker's rights subprogram to a definer's rights subprogram that queries or updates the table containing the sensitive data. Although multiple users can call the invoker's rights subprogram, they do not have direct access to the sensitive data.
Data dictionary views for subprograms
SQL> desc user_source;
Name Type
Nullable Default
Comments
----
-------------- -------- -------
-------------------------------------------------------------------------------------------------------------
NAME
VARCHAR2(30) Y
Name
of the object
TYPE
VARCHAR2(12) Y Type of the object:
"TYPE", "TYPE BODY", "PROCEDURE", "FUNCTION","PACKAGE",
"PACKAGE BODY" or "JAVA SOURCE"
LINE
NUMBER Y Line number of this line
of source
TEXT VARCHAR2(4000) Y Source text
DBA_OBJECTS
Describes all objects in the database.
Describes all objects in the database.
Not NULL
|
Description
|
||
OWNER
|
NOT NULL
|
VARCHAR2(30)
|
Owner of the object
|
OBJECT_NAME
|
NOT NULL
|
VARCHAR2(128)
|
Name of the object
|
SUBOBJECT_NAME
|
VARCHAR2(30)
|
Name of the subobject (for example,
partition)
|
|
OBJECT_ID
|
NOT NULL
|
NUMBER
|
Dictionary object number of the
object
|
DATA_OBJECT_ID
|
NUMBER
|
Dictionary object number of the
segment that contains the object. Not the same as unique 16-byte object
identifier (object ID) that Oracle assigns to row objects in object tables in
the system
|
|
OBJECT_TYPE
|
VARCHAR2(18)
|
Type of the object (such as
TABLE , INDEX ) |
|
CREATED
|
NOT NULL
|
DATE
|
Timestamp for the creation of the
object
|
LAST_DDL_TIME
|
NOT NULL
|
DATE
|
Timestamp for the last modification
of the object resulting from a DDL command (including grants and revokes)
|
TIMESTAMP
|
VARCHAR2(19)
|
Timestamp for the specification of
the object (character data)
|
|
STATUS
|
VARCHAR2(7)
|
Status of the object (
VALID , INVALID , or N/A) |
|
TEMPORARY
|
VARCHAR2(1)
|
Whether the object is temporary
(the current session can see only data that it placed in this object itself)
|
|
GENERATED
|
VARCHAR2(1)
|
Was the name of this object system
generated? (
Y|N ) |
|
SECONDARY
|
VARCHAR2(1)
|
Whether this is a secondary object
created by the ODCIIndexCreate method of the Oracle9i Data Cartridge (
Y|N ) |
.
Oracle 11gR1
DBA_PROCEDURES lists all functions and
procedures along with their associated properties. Its columns are the same as
those in "ALL_PROCEDURES".
Column
|
Datatype
|
NULL
|
Description
|
OWNER
|
VARCHAR2(30)
|
NOT NULL
|
Owner
of the procedure
|
OBJECT_NAME
|
VARCHAR2(30)
|
NOT NULL
|
Name
of the object: top-level function, procedure, or package name
|
PROCEDURE_NAME
|
VARCHAR2(30)
|
Name
of the procedure
|
|
OBJECT_ID
|
NUMBER
|
Object
number of the object
|
|
SUBPROGRAM_ID
|
NUMBER
|
Unique
subprogram identifier
|
|
OVERLOAD
|
VARCHAR2(40)
|
Overload
unique identifier
|
|
OBJECT_TYPE
|
VARCHAR2(19)
|
The
typename of the object
|
|
AGGREGATE
|
VARCHAR2(3)
|
Indicates
whether the procedure is an aggregate function (YES) or
not (NO)
|
|
PIPELINED
|
VARCHAR2(3)
|
Indicates
whether the procedure is a pipelined table function (YES) or
not (NO)
|
|
IMPLTYPEOWNER
|
VARCHAR2(30)
|
Name
of the owner of the implementation type, if any
|
|
IMPLTYPENAME
|
VARCHAR2(30)
|
Name
of the implementation type, if any
|
|
PARALLEL
|
VARCHAR2(3)
|
Indicates
whether the procedure or function is parallel-enabled (YES) or
not (NO)
|
|
INTERFACE
|
VARCHAR2(3)
|
YES, if
the procedure/function is a table function implemented using the ODCI
interface; otherwise NO
|
|
DETERMINISTIC
|
VARCHAR2(3)
|
YES, if
the procedure/function is declared to be deterministic; otherwise NO
|
|
AUTHID
|
VARCHAR2(12)
|
Indicates
whether the procedure/function is declared to execute as DEFINER or CURRENT_USER
(invoker)
|
To drop a stored procedure/function
drop procedure <procedure_name>;
drop function <function_name>;
When
client executes a procedure are function, the processing is done in the server.
This
reduces network traffic. The subprograms are compiled and stored in the Oracle
database as stored programs and can be invoked whenever required.
As
they are stored in compiled form when called they only need to be executed.
Hence they save time needed for compilation.
Subprograms
provide the following advantages
1.
They
allow you to write PL/SQL program that meet our need
2.
They
allow you to break the program into manageable modules.
3.
They
provide reusability and maintainability for the
code.
Discovering Errors
PL/SQL does not always tell you about compilation errors. Instead,
it gives you a cryptic message such as "procedure created with compilation
errors". If you don't see what is wrong immediately, try issuing the
command
show errors procedure
<procedure_name>;
Alternatively, you can type, SHO ERR (short
for SHOW ERRORS) to
see the most recent compilation error.
Note
that the location of the error given as part of the error message is not always
accurate!
The following is a simple example of a procedure with in parameter :
CREATE OR REPLACE Procedure
UpdateCourse
( name_in IN varchar2 )
IS
cnumber number;
( name_in IN varchar2 )
IS
cnumber number;
cursor c1 is
select course_number
from courses_tbl
where course_name = name_in;
select course_number
from courses_tbl
where course_name = name_in;
BEGIN
open c1;
fetch c1 into cnumber;
if c1%notfound then
cnumber := 9999;
end if;
fetch c1 into cnumber;
if c1%notfound then
cnumber := 9999;
end if;
insert into student_courses
( course_name,
course_number)
values ( name_in,
cnumber );
( course_name,
course_number)
values ( name_in,
cnumber );
commit;
close c1;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
This procedure is called UpdateCourse. It has one parameter called name_in.
The procedures will lookup the course_number based on course name. If it does
not find a match, it defaults the course number to 99999. It then inserts a new
record into the student_courses table.WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
Oracle Stored Procedures Tips
http://www.dba-oracle.com/art_proc.htm
Faqs
What
is the difference between "IS" and "AS" while creating
procedure. Ex:- create procedure IS or AS
How
one call DDL statement using stored procedures in Oracle?
Explain
the benefits of running stored procedure on a database engine?
Stored Procedure are of two type
1-user define stored procedure
2- System define Stored procedure
1-user define stored procedure
2- System define Stored procedure
Q) Is it possible to
know from the select statement if it is INVOKER(CURRENT_USER) or DEFINER
A) Yes, It is possible to get this information from the select statement. Use
SELECT dbo.object_name,
(DECODE(SIGN(bitand(options,16)),1,'INVOKER','DEFINER')) "authid"
FROM dba_objects dbo,
sys.PROCEDURE$ p
WHERE p.obj# = dbo.object_id
AND dbo.object_name = "Your Package Name"
AND dbo.object_type = 'PACKAGE'
AND dbo.owner = 'APPS'
Example:-
-----------
SELECT dbo.object_name,
(DECODE(SIGN(bitand(options,16)),1,'INVOKER','DEFINER')) "authid"
FROM dba_objects dbo,
sys.PROCEDURE$ p
WHERE p.obj# = dbo.object_id
AND dbo.object_name = 'ASO_APR_WF_INT'
AND dbo.object_type = 'PACKAGE'
AND dbo.owner = 'APPS'
A) Yes, It is possible to get this information from the select statement. Use
SELECT dbo.object_name,
(DECODE(SIGN(bitand(options,16)),1,'INVOKER','DEFINER')) "authid"
FROM dba_objects dbo,
sys.PROCEDURE$ p
WHERE p.obj# = dbo.object_id
AND dbo.object_name = "Your Package Name"
AND dbo.object_type = 'PACKAGE'
AND dbo.owner = 'APPS'
Example:-
-----------
SELECT dbo.object_name,
(DECODE(SIGN(bitand(options,16)),1,'INVOKER','DEFINER')) "authid"
FROM dba_objects dbo,
sys.PROCEDURE$ p
WHERE p.obj# = dbo.object_id
AND dbo.object_name = 'ASO_APR_WF_INT'
AND dbo.object_type = 'PACKAGE'
AND dbo.owner = 'APPS'
Faqs related to data dictionary views:
To
find out what procedures and functions you have created, use the following SQL
query:
select object_type, object_name
from user_objects
where object_type = 'PROCEDURE'
or object_type =
'FUNCTION';
SQL to display all stored procedures
in my database
Question: I want the SQL to display all stored procedures in my database. I also want to know how to show the source for Oracle stored procedures. Where do I find stored procedure information in Oracle dictionary?
Answer:
The dba_source view contains the details on Oracle stored procedures and it’s easy to query dba_source to see stored procedure details.
The dba_source view contains the details on Oracle stored procedures and it’s easy to query dba_source to see stored procedure details.
For a roadmap to the dictionary
views, get the free Oracle poster,
indispensible for these types of SQL queries.
The DBA_SOURCE view is based on
the SOURCE$ table that holds all of the source code for the stored objects
(other than triggers and views) in the database.
Name
Null? Type
------------------------------------------------------------------
OWNER VARCHAR2 (30)
NAME VARCHAR2(30)
TYPE VARCHAR2(12)
LINE NUMBER
TEXT VARCHAR2(4000)
------------------------------------------------------------------
OWNER VARCHAR2 (30)
NAME VARCHAR2(30)
TYPE VARCHAR2(12)
LINE NUMBER
TEXT VARCHAR2(4000)
Notice that the TEXT column is
a VARCHAR2(4000) data type. This 4000 length indicates that to properly view
any text lines you may need to set the LONG variable in SQL*Plus to 4000.
A simple select will return all
of the lines for a given stored object in order as shown in Figure 6.
select 'create or replace '||text,line
from
dba_source
where
owner = upper('&&owner') and
type = upper('&&obj_type') and
name = upper('&&obj_name') and
line = 1
UNION
select text,line
from
dba_source s2
where
s2.name = upper('&&3') and
s2.owner = upper('&&1') and
s2.type = upper('&&2') and
s2.line > 1
order by 2;
from
dba_source
where
owner = upper('&&owner') and
type = upper('&&obj_type') and
name = upper('&&obj_name') and
line = 1
UNION
select text,line
from
dba_source s2
where
s2.name = upper('&&3') and
s2.owner = upper('&&1') and
s2.type = upper('&&2') and
s2.line > 1
order by 2;
Q1: How do you invoke a stored procedure in a SELECT statement?
Expert Brian Peasland:
You cannot invoke a stored procedure in a SELECT statement.
However, you can call a function in a SELECT statement.
The function can be a wrapper for the stored procedure. For
instance, assume that I have a stored procedure called FOO. Let's create a
wrapper function BAR that calls the stored proc:
CREATE FUNCTION bar ()
RETURN number
AS
BEGIN
foo();
RETURN 1;
END;
/
Now I can use the function above to execute the stored proc in
my SELECT statement:
SELECT bar() FROM dual;
Q2: I have a situation to call the same stored procedure from inside the same procedure. For example, let's say I have a procedure called ConverSubPlans with some parameters. I am doing some validations inside that procedure and based on those, I need to call ConverSubPlans once again within ConverSubPlans. Is it advisable?
Expert Brian Peasland: You sure can call a
procedure from within that same procedure. Such an operation is called
"recursion". One procedure recursively calls itself. The big thing to
keep in mind is that you need an ending point otherwise the recursive calls
will be infinite and never stop. A common recursive procedure or function is to
compute the factorial of a number. N factorial (written N!) is defined as
N*(N-1)*(N-2)*...*2*1. This also means that N! = N*(N-1)!. So a recursive
function is born. Such a recursive function would appear as follows:
CREATE FUNCTION fact (n NUMBER)
RETURN NUMBER IS
returnVal NUMBER;
BEGIN
IF (n = 1) THEN
returnVal := 1;
ELSE
returnVal := n*fact(n-1);
END IF;
RETURN returnVal;
END;
/
Notice that in the above example, I have a
terminating condition (n=1). If this condition is not met, then the function is
called again. The same concept applies to procedures. But ensure that you have
a terminating condition.
Q3.Oracle: how can one search plsql code for a string or key value
The text source of the stored objects
(including stored procedures) are made available in Oracle by three views:
- USER_SOURCE describes the text source of the stored objects
owned by the current user. This view does not display the OWNER column.
- ALL_SOURCE describes the text source of the stored objects
accessible to the current user.
- DBA_SOURCE describes the text source of all stored objects
in the database.
These are the columns:
Column Name
|
Description
|
OWNER
|
Owner of the object
|
NAME
|
Name of the object
|
TYPE
|
Type of object: FUNCTION, JAVA SOURCE,
PACKAGE, PACKAGE BODY, PROCEDURE, TRIGGER, TYPE, TYPE BODY
|
LINE
|
Line number of this line of source
|
TEXT
|
Text source of the stored object
|
If you want to search for a certain keyword
in the source, this query may be helpful:
SELECT type,
name, line
FROM user_source
WHERE
UPPER(text) LIKE UPPER ('%&SEARCH_STRING%');
Enter the string you are looking for when prompted for the value of SEARCH_STRING.
Q4:How
can one see if somebody modified any code?
The source code for
stored procedures, functions and packages are stored in the Oracle Data
Dictionary. One can detect code changes by looking at the TIMESTAMP and
LAST_DDL_TIME column in the USER_OBJECTS dictionary view. Example:
SELECT OBJECT_NAME,
TO_CHAR(CREATED, 'DD-Mon-RR HH24:MI') CREATE_TIME,
TO_CHAR(LAST_DDL_TIME, 'DD-Mon-RR
HH24:MI') MOD_TIME,
STATUS
FROM USER_OBJECTS
WHERE LAST_DDL_TIME > '&CHECK_FROM_DATE';
Note: If you recompile
an object, the LAST_DDL_TIME column is updated, but the TIMESTAMP column is not
updated.
If you modified the
code, both the TIMESTAMP and LAST_DDL_TIME columns are updated.
Q5: I am encountering a very strange problem....when I create the following query in SQL Plus
SELECT * FROM USER_OBJECTS;
then only the records under the OBJECT_NAME
column get displayed; the rest of the columns simply get ignored!!! Why is this
happening? If I change the query to
SELECT OBJECT_NAME,OBJECT_ID,OBJECT_TYPE
FROM USER_OBJECTS;
then again only the records under the
OBJECT_NAME column get displayed but if I change the query to
SELECT OBJECT_ID,OBJECT_TYPE,OBJECT_NAME
FROM USER_OBJECTS;
then the records of all the 3 columns get
displayed!! If the query is changed to
SELECT OBJECT_ID,OBJECT_NAME,OBJECT_TYPE
FROM USER_OBJECTS;
then only the records under the OBJECT_ID
& OBJECT_NAME columns get displayed!!! Can someone throw some light on this
erratic behaviour?
Thanks,
Arpan
Solution for the above problem:
CRoberts
(MIS) 23 Feb 03 21:20
I may have a solution to your problem. It is simply the way SQL*Plus displays
columns.
It has to do with what the SET LINESIZE n
is set to.
Numbers are limited to NUMBER(38) so your
Object_ID will be displayed.
However, if a text column, like Object_Name
is displayed, you can get '--- ...' forevery.
Two ways to cure this. One is use
a column command like COLUMN OBJECT_NAME FORMAT A30 TRUNC and so on for each
Text column.
The other is to SET LINESIZE 80 or
whatever.
Try this test:
DBSBE> set linesize 300
DBSBE> desc user_tables
Name
---------------------------------------- . . .
TABLE_NAME
TABLESPACE_NAME
DBSBE> set linesize 80
DBSBE> desc user_obects
DBSBE> desc user_objects
Name Null? Type
---------------------------- --------
-------------
OBJECT_NAME VARCHAR2(128)
SUBOBJECT_NAME VARCHAR2(30)
arpan (Programmer) 24 Feb 03 2:48
Hi,
Thanks for your response. Before posting my
question, I had thought that the LINESIZE could be the culprit since when the
LINESIZE is set to 80 (which is the default value)
SELECT * FROM USER_OBJECTS;
says 'rows will be truncated'. When the
LINESIZE is increased to 260, then the message 'rows will be truncated' was not
shown but at the same time, only the records under the OBJECT_NAME column were
displayed!! So I don't think LINESIZE is the reason behind this erratic
behavior.
I tried out using COLUMN OBJECT_NAME FORMAT
A30 TRUNC & then all the records under the columns other than the
OBJECT_NAME column were displayed. But I couldn't exactly follow what does
COLUMN OBJECT_NAME FORMAT A30 TRUNC do? What does 'A30' mean or what it does?
Could you please just explain me this? Also I have noticed that if A30 is
changed to A1, still it doesn't make any difference to the output. Why so?
sem (Programmer) 24 Feb 03 4:31
In fact sql*plus has some problems with
increasing linesize. In some cases resizing(maximaizing) its window may help.
Regards, Dima
No comments:
Post a Comment