Pl/sql: Procedural Language Extension To Sql

  • Uploaded by: Irfan
  • 0
  • 0
  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Pl/sql: Procedural Language Extension To Sql as PDF for free.

More details

  • Words: 6,476
  • Pages: 100
IBM Global Services

IBM Global Services India

PL/SQL Procedural Language Extension to SQL

© Copyright IBM Corporation 2007 2002

16/07/2007 IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Today’s Topics  Oracle Architecture and Overview  Error Handling  Stored Procedures 

Procedure



Function



Package

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL - Introduction  Procedural extension allowing for modularity, variable declaration, loops and logical constructs. Allows for advanced error handling Communicates natively with other oracle database objects. Managed centrally within the Oracle database. PL/SQL Blocks of code can be embedded in host languages Using PL/SQL, you can define and execute PL/SQL procedures, functions and packages PL/SQL engine executes PL/SQL blocks of code

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL – Why Use Manage business rules – through middle layer application logic. Generate code for triggers Generate code for interface Enable database-centric client/server applications Execution privileges can be better managed

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL Engine PL/SQL Engine PL/SQL block

Procedural Procedural Statement Statement Executor

PL/SQL block SQL

SQL Statement Executor

Oracle Server IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL Structure

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL Block Type

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL Block Type DECLARE v_item_code VARCHAR2(6); v_item_descr VARCHAR2(20); BEGIN v_item_code := 'ITM101'; v_item_descr := 'Spare parts'; INSERT INTO items_tab VALUES (v_item_code, v_item_descr); EXCEPTION WHEN OTHERS THEN dbms_output.put_line(SQLERRM); END; To make this procedure work, the SQL*Plus environment variable SERVEROUTPUT should be set to ON. Here's the code to do this in SQL*Plus: SQL> set serveroutput on; IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL Data Type

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

PL/SQL Control Structures  Conditional Control: IF and CASE Statements  Iterative Control: LOOP and EXIT Statements - simple or infinite loop - FOR loop - WHILE loop  Sequential Control: GOTO and NULL Statements

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

IF Constructor IF age >= 65 THEN

IF THEN

INSERT INTO retired

....

VALUES(name, age, lodging);

END IF;

ELSIF age <18 THEN

IF THEN

INSERT INTO underage

.... [ELSIF THEN] ......

VALUES(name, age, lodging); ELSE

[ELSE]

INSERT INTO workforce

...

VALUES(name, age, lodging);

END IF;

END IF;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

CASE Statement CASE grade WHEN ’A’ THEN dbms_output.put_line(’Excellent’); WHEN ’B’ THEN dbms_output.put_line(’Very Good’); WHEN ’C’ THEN dbms_output.put_line(’Good’); WHEN ’D’ THEN dbms_output.put_line(’Fair’); WHEN ’F’ THEN dbms_output.put_line(’Poor’); ELSE dbms_output.put_line(’No such grade’); END CASE;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

LOOP … END LOOP LOOP rem_balance := account_balance(accno); IF rem_balance < 100

THEN

EXIT; ELSE decrement_balance(accno,withdraw_amt); END IF; END LOOP;  Can also use EXIT WHEN to conditionally exit from a loop  If you don’t specify an exit condition, it becomes an infinite loop

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

FOR Loop 1. FOR

even_number IN 1..50

LOOP calc_values(even_number * 2); END LOOP; 2.

FOR even_number IN REVERSE 1..10 LOOP calc_values(even_number*2); END LOOP;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

WHILE Loops DECLARE TEN number:=10; i number_table.num%TYPE:=1; BEGIN WHILE i <= TEN LOOP INSERT INTO number_table VALUES(i); i := i + 1; END LOOP; END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

GOTO Statement  To unconditionally transfer control.  GOTO  At least one statement must follow a label  You cannot transfer into an IF construct  You cannot go to the middle of a LOOP  You cannot transfer control from an executable section to an exception and vice versa  You cannot use GOTO to enter a block

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

What are CURSOR ???  Cursors are memory areas that allow you to allocate an area of memory and access the information retrieved from a SQL statement.  A cursor is a symbolic name associated with a select statement.  Cursors are special programming constructs that allow data to be manipulated on a row-by-row basis.  You can think of a cursor as a pointer into a table in the database. IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Types of Cursors  Implicit Cursors  Get created automatically every time you use an INSERT, UPDATE, DELETE or SELECT command  Doesn’t need to be declared.  Symbolic Name is SQL

 Explicit Cursors  Needs to be explicitly created  Symbolic Name is user-given.  Used if query returns more than one record.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Implicit Cursor Example DECLARE v_sname VARCHAR2(10); v_rating NUMBER(3); BEGIN SELECT sname, rating INTO v_sname, v_rating FROM Sailors WHERE sid = '112'; END; / • INTO clause is required. • Query must return exactly one row. • Otherwise, a NO_DATA_FOUND or TOO_MANY_ROWS exception is thrown IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Implicit Cursor Attributes  Return information about the execution of the last INSERT, UPDATE, DELETE, or SELECT INTO statement. It has 4 useful attributes

SQL%ROWCOUNT

Number of rows affected by the most recent SQL statement (an integer value).

SQL%FOUND

Boolean attribute that evaluates to TRUE if the most recent SQL statement affects one or more rows.

SQL%NOTFOUND

Boolean attribute that evaluates to TRUE if the most recent SQL statement does not affect any rows.

SQL%ISOPEN

Always evaluates to FALSE because PL/SQL closes implicit cursors immediately after they are executed.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Implementation of %rowcount SQL> begin 2 update emp1 3 set sal = sal + 500 4 where empno=&emp_no; 5 if sql%rowcount = 1 then 6 dbms_output.put_line('Employee Successfully Updated'); 7 end if; 8 end; 9 / Enter value for emp_no: 8003 old 4: where empno=&emp_no; new 4: where empno=8003; Employee Successfully Updated PL/SQL procedure successfully completed.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Another Implementation 1 declare 2 vsal number; 3 begin 4 select sal into vsal 5 from emp1 6 where empno=&emp_no; 7 if sql%found then 8 dbms_output.put_line('Employee Successfully Found'); 9 else 10 dbms_output.put_line('Employee Not Successfully Found'); 11 end if; 12 exception 13 when no_data_found then 14 dbms_output.put_line('Employee Not Found'); 15* end; 16 / Enter value for emp_no: 8009 old 6: where empno=&emp_no; new 6: where empno=8009; Employee Not Found

PL/SQL procedure successfully completed.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Explicit Cursor Manipulation The process of working with an cursor consists of the following steps:  Declaring the cursor. This initializes the cursor into memory.  Opening the cursor. The previously declared cursor can now be opened; memory is allotted.  Fetching the cursor. Previously declared and opened cursor can now retrieve data; this is the process of fetching the cursor.  Closing the cursor. Previously declared, opened, and fetched cursor must now be closed to release memory allocation IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Declaring Cursor  Declaring a cursor defines the name of the cursor and associates it with a SELECT statement. Syntax: CURSOR <cursor_name> IS select statement e.g. Cursor c_myCursor is Select emp.name, emp.dept from employee where salary > 5000; IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Opening a Cursor When the Open cursor statement is processed, the following four actions will take place automatically: 1. The variables (including bind variables) in the WHERE clause are examined. 2. Based on the values of the variables, the active set is determined and the PL/SQL engine executes the query for that cursor. Variables are examined at cursor open time only. 3. The PL/SQL engine identifies the active set of data—the rows from all involved tables that meet the WHERE clause criteria. 4. The active set pointer is set to the first row.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Fetching Records After the cursor has been declared and opened, you can then retrieve data from the cursor. The process of getting the data from the cursor is referred to as fetching the cursor. There are two methods of fetching a cursor, done with the following command:

1. FETCH cursor_name INTO PL/SQL variables; OR 3. FETCH cursor_name INTO PL/SQL record;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Explicit Cursor Attributes <cursor_name>

%NOTFOUND

A Boolean attribute that returns TRUE if the previous FETCH did not return a row, and FALSE if it did.

<cursor_name>

%FOUND

A Boolean attribute that returns TRUE if the previous FETCH returned a row, and FALSE if it did not

<cursor_name>

%ROWCOUNT

Number of records fetched from a cursor at that point in time.

<cursor_name>

%ISOPEN

A Boolean attribute that returns TRUE if cursor is open, FALSE if it is not.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Closing Cursor  Once all of the rows in the cursor have been processed (retrieved), the cursor should be closed.  This tells the PL/SQL engine that the program is finished with the cursor, and the resources associated with it can be freed. The syntax for closing the cursor is CLOSE cursor_name;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Putting it all Together… declare --DECLARE CURSOR cursor trial_cursor IS Select emp_name, salary from employee; myname employee.emp_name%type; mysal employee.salary%type; BEGIN if not trial_cursor%isopen then open trial_cursor; --OPEN CURSOR end if; loop --FETCH From CURSOR into VARIALBLES fetch trial_cursor into myname, mysal; dbms_output.put_line(myname || ' ' || mysal); Exit when trial_cursor%NOTFOUND = true; end loop; dbms_output.put_line('No.of rows in Cursor are: ' || trial_cursor%rowcount); close trial_cursor; --CLOSING CURSOR End; IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Cursor with For Loop  Automatically opens the cursor, fetches the records, then closes the cursor  FOR variable_name(s) IN cursor_name LOOP processing commands END LOOP;  Cursor variables cannot be used outside loop

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

An Example declare cursor c_emp_cursor IS Select * from employee; BEGIN FOR myrow IN c_emp_cursor LOOP

--NO OPEN

dbms_output.put_line(myrow.Emp_Name || ' ' || myrow.Salary); --NO FETCH

--NO CLOSE

end loop;

dbms_output.put_line('All operations performed Implicitly'); End;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Using Subqueries Instead of Explicit Cursors You need not declare a cursor because PL/SQL lets you substitute a subquery. The following cursor FOR loop calculates a bonus, then inserts the result into a database table: DECLARE bonus REAL; BEGIN FOR emp_rec IN (SELECT empno, sal, comm FROM emp) LOOP bonus := (emp_rec.sal * 0.05) + (emp_rec.comm * 0.25); INSERT INTO bonuses VALUES (emp_rec.empno, bonus); END LOOP; COMMIT; END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Passing Parameters to Explicit Cursors To Pull different sets of records in the same cursor, one can pass parameter to the cursor at the time of opening. An explicit cursor can take parameters and return a data set for a specific parameter value. This eliminates the need to define multiple cursors and hard-code a value in each cursor. DECLARE CURSOR emp_cursor(dnum NUMBER) IS SELECT sal, comm FROM emp WHERE deptno = dnum; total_wages NUMBER(11,2) := 0; high_paid NUMBER(4) := 0; higher_comm NUMBER(4) := 0; BEGIN /* the number of iterations will equal the number of rows * * returned by emp_cursor */ FOR emp_record IN emp_cursor(20) LOOP emp_record.comm := NVL(emp_record.comm,0); total_wages := total_wages + emp_record.sal + emp_record.comm; IF emp_record.sal > 2000 THEN high_paid := high_paid + 1; END IF; END LOOP; INSERT INTO temp VALUES (high_paid, higher_comm, 'Total Wages: ' || TO_CHAR(total_wages)); COMMIT; END; IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

SELECT FOR UPDATE Cursors You use SELECT FOR UPDATE cursors for updating the rows retrieved by a cursor. This is often required when there’s a need to modify each row retrieved by a cursor without having to re-fetch that row.

Defining a SELECT FOR UPDATE Cursor

DECLARE CURSOR csr_1 IS SELECT * FROM sec_hrc_tab FOR UPDATE OF hrc_descr; BEGIN /* . . . Open the cursor and process the resultset . . . */ END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Using a SELECT FOR UPDATE Cursor

Once you’ve defined a SELECT FOR UPDATE cursor, you use the WHERE CURRENT OF clause to process the rows returned by it. You can use this clause in an UPDATE or DELETE statement. DECLARE CURSOR csr_1 IS SELECT * FROM sec_hrc_tab FOR UPDATE OF hrc_descr; v_hrc_descr VARCHAR2(20); BEGIN FOR idx IN csr_1 LOOP v_hrc_descr := UPPER(idx.hrc_descr); UPDATE sec_hrc_tab SET hrc_descr = v_hrc_descr WHERE CURRENT OF csr_1; END LOOP; COMMIT; END; IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Cursor Variables  An explicit cursor once declared is associated with a specific query—only the one specific query that was known at compile time. In this way, the cursor declared was static and couldn’t be changed at runtime.  A cursor variable is a single PL/SQL variable that you can associate with different queries at runtime. Why Use Cursor Variables?

The primary advantage of using cursor variables is their capability to pass resultsets between stored subprograms. Before cursor variables, this wasn’t possible. Now, with cursor variables, the work area that a cursor variable points to remains accessible as long as the variable points to it. Another advantage of cursor variables is their introduction of a sort of dynamism, in that a single cursor variable can be associated with multiple queries at runtime.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Defining a Cursor Variable

 Defining a cursor variable consists of defining a pointer of type REF CURSOR and defining a variable of this type. First it involves the definition of a REF CURSOR first, as shown here: TYPE rc IS REF CURSOR; The next step is to declare a variable of this type. Here’s the code for this: v_rc rc; So the complete declaration of a cursor variable is as follows: TYPE rc IS REF CURSOR;   v_rc rc; This code suggests that rc is a pointer of type CURSOR and v_rc (in fact, any variable) defined of type rc points to a SQL cursor.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

A Complete Example DECLARE TYPE rc is REF CURSOR; v_rc rc; hrc_rec hrc_tab%ROWTYPE; BEGIN OPEN v_rc FOR SELECT * from hrc_tab; dbms_output.put_line(‘Hierarchy Details’); dbms_output.put_line(‘------------------------’); dbms_output.put_line(‘Code’||’ ‘||rpad(‘Description’,20,’ ‘)); dbms_output.put_line(rpad(‘-’,4,’-’)||’ ‘||rpad(‘-’,20,’-’)); LOOP FETCH v_rc INTO hrc_rec; EXIT WHEN v_rc%NOTFOUND; dbms_output.put_line(to_char(hrc_rec.hrc_code)||’ ‘|| rpad(hrc_rec.hrc_descr,20,’ ‘)); END LOOP; CLOSE v_rc; END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Strong and Weak REF CURSOR Types

 The Ref Cursor variable which doesn’t dictate the return type of the cursor is a WEAK Ref Cursor Type. For eg TYPE rc IS REF CURSOR; v_rc rc; Hence, it can point to any SELECT query with any number of columns.

 A strong REF CURSOR type definition specifies a return type. TYPE rc is REF CURSOR RETURN hrc_tab%ROWTYPE; v_rc rc;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Weak REF CURSOR Example DECLARE TYPE tcursor IS REF CURSOR; tcur tcursor; e1 emp%ROWTYPE; d1 dept%ROWTYPE; tname VARCHAR2(20); BEGIN tname := &tablename; IF tname = 'emp' THEN OPEN tcur FOR SELECT * FORM emp; DBMS_OUTPUT.PUT_LINE ('Emp table opened.'); close tcur; DBMS_OUTPUT.PUT_LINE ('Emp table closed.'); ELSE IF tname = 'dept' THEN OPEN tcur FOR SELECT * FROM dept; DBMS_OUTPUT.PUT_LINE ('Dept table opened.'); close tcur; DBMS_OUTPUT.PUT_LINE ('Emp table closed.'); ELSE RAISE_APPLICATION_ERROR (-20004, 'Table name is wrong'); END IF; END; IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Strong REF CURSOR Example

DECLARE TYPE ecursor IS REF CURSOR RETURN emp%ROWTYPE; ecur ecursor; e_rec emp%ROWTYPE; dn NUMBER; BEGIN dn := &deptno; OPEN ecur FOR SELECT * FROM emp WHERE deptno = dn; FOR e_rec IN ecur LOOP DBMS_OUTPUT.PUT_LINE ('Employee No : ' || e_rec.empno); DBMS_OUTPUT.PUT_LINE ('Employee Salary: ' || e_rec.salary); END LOOP; END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating Procedures 

A procedure is a named PL/SQL block that performs an action.

 A procedure can be stored in the database, as a database object, for repeated execution.

CREATE [OR REPLACE] PROCEDURE procedure_name (argument1 [mode1] datatype1, argument2 [mode2] datatype2, . . .) IS [AS] PL/SQL Block;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Developing Stored Procedures Oracle Procedure Builder

Edit

System editor

1

Text file Store in database Source code Compile

2

parsed-code Execute IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating a Stored Procedure Using SQL*Plus 1. Enter the text of the CREATE PROCEDURE statement in a system editor or word processor and save it as a script file (.sql extension). 1. From SQL*Plus, run the script file to compile the source code into parsed-code and store both in the database. 1. Invoke the procedure from an Oracle Server environment to determine whether it executes without error.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Stored Procedures : Example

SQL> CREATE OR REPLACE PROCEDURE raise_salary 2 (v_id in emp.empno%TYPE) 3 IS 4 BEGIN 5 UPDATE emp 6 SET sal = sal * 1.10 7 WHERE empno = v_id; 8 END raise_salary; 9 / Procedure created. SQL> EXECUTE raise_salary (7369) PL/SQL procedure successfully completed.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Invoking a Procedure from an Anonymous PL/SQL Block

DECLARE v_id NUMBER := 7900; BEGIN raise_salary(v_id); COMMIT; ...

--invoke procedure

END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Invoking a Procedure from a Stored Procedure

SQL> CREATE OR REPLACE PROCEDURE process_emps 2 IS 3 CURSOR emp_cursor IS 4 SELECT empno 5 FROM emp; 6 BEGIN 7 FOR emp_rec IN emp_cursor LOOP 8 raise_salary(emp_rec.empno); --invoke procedure 9 END LOOP; 10 COMMIT; 11 END process_emps; 12 /

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Procedural Parameter Modes Procedure

Calling environment

IN parameter OUT parameter IN OUT parameter (DECLARE) BEGIN EXCEPTION END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Parameter Modes for Formal Parameters IN

OUT

IN OUT

Default

Must be specified

Must be specified

Value is passed into subprogram

Returned to calling environment

Passed into subprogram; returned to calling environment

Formal parameter acts as a constant

Uninitialized variable Initialized variable

Actual parameter can be a literal, expression, constant, or initialized variable

Must be a variable

IGSI Confidential

|

Wednesday, August 5, 2009

Must be a variable

© Copyright IBM Corporation 2003

IBM Global Services

IN Parameters: Example 7369

v_id

SQL> CREATE OR REPLACE PROCEDURE raise_salary 2 (v_id in emp.empno%TYPE) 3 IS 4 BEGIN 5 UPDATE emp 6 SET sal = sal * 1.10 7 WHERE empno = v_id; 8 END raise_salary; 9 / Procedure created. SQL> EXECUTE raise_salary (7369) PL/SQL procedure successfully completed. IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

OUT Parameters: Example Calling environment

QUERY_EMP procedure

7654

v_id MARTIN v_name

IGSI Confidential

|

Wednesday, August 5, 2009

1250

v_salary

1400

v_ comm

© Copyright IBM Corporation 2003

IBM Global Services

OUT Parameters: Example SQL> 1 2 3 4 5 6 7 8 9 10 11 12

CREATE OR REPLACE PROCEDURE query_emp (v_id IN emp.empno%TYPE, v_name OUT emp.ename%TYPE, v_salary OUT emp.sal%TYPE, v_comm OUT emp.comm%TYPE) IS BEGIN SELECT ename, sal, comm INTO v_name, v_salary, v_comm FROM emp WHERE empno = v_id; END query_emp; /

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

OUT Parameters and SQL*Plus SQL> START emp_query.sql Procedure created. SQL> VARIABLE g_name SQL> VARIABLE g_salary SQL> VARIABLE g_comm

varchar2(15) number number

SQL> EXECUTE query_emp (7654, :g_name, :g_salary, 2 :g_comm) PL/SQL procedure successfully completed. SQL> PRINT g_name G_NAME --------------MARTIN

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

IN OUT Parameters Calling environment '(800)633-0575'

'(800)633-0575'

SQL> CREATE OR REPLACE PROCEDURE format_phone 2 (v_phone_no IN OUT VARCHAR2) 3 IS 4 BEGIN 5 v_phone_no := '(' || SUBSTR(v_phone_no,1,3) || 6 ')' || SUBSTR(v_phone_no,4,3) || 7 '-' || SUBSTR(v_phone_no,7); 8 END format_phone; 9 /

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Invoking FORMAT_PHONE from SQL*Plus SQL>VARIABLE g_phone_no varchar2(15) SQL> BEGIN :g_phone_no := '8006330575'; END; 2 / PL/SQL procedure successfully completed. SQL> EXECUTE format_phone (:g_phone_no) PL/SQL procedure successfully completed. SQL> PRINT g_phone_no G_PHONE_NO --------------(800)633-0575

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Passing Large Data Structures with the NOCOPY Compiler Hint  When you call the subprogram, the IN parameter is passed by reference. That is, a pointer to the IN actual parameter is passed to the corresponding formal parameter.  By default, the OUT and IN OUT parameters are passed by value.  When the parameters hold large data structures such as collections, records, and instances of object types, all this copying slows down execution and uses up memory.  To prevent that, you can specify the NOCOPY hint, which allows the PL/SQL compiler to pass OUT and IN OUT parameters by reference. PROCEDURE getEmployees ( ptab_emp_id

OUT NOCOPY

tab_emp_id,

ptab_firstname

OUT NOCOPY

tab_firstname,

ptab_lastname

OUT NOCOPY

tab_lastname )

IS BEGIN ……………… End IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Methods for Passing Parameters  Positional  Named  Combination

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Passing Parameters: Example Procedure SQL> 1 2 3 4 5 6 7 8

CREATE OR REPLACE PROCEDURE add_dept (v_name IN dept.dname%TYPE DEFAULT 'unknown', v_loc IN dept.loc%TYPE DEFAULT 'unknown') IS BEGIN INSERT INTO dept VALUES (dept_deptno.NEXTVAL, v_name, v_loc); END add_dept; /

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Examples of Passing Parameters SQL> 2 3 4

begin add_dept; add_dept ( 'TRAINING', 'NEW YORK'); add_dept ( v_loc => 'DALLAS', v_name => 'EDUCATION') ; 5 add_dept ( v_loc => 'BOSTON') ; 6 end; 7 / PL/SQL procedure successfully completed. SQL>

SELECT * FROM dept;

DEPTNO -----... 41 42 43 44

DNAME -------------... unknown TRAINING EDUCATION unknown

IGSI Confidential

|

Wednesday, August 5, 2009

LOC ------------... unknown NEW YORK DALLAS BOSTON © Copyright IBM Corporation 2003

IBM Global Services

Removing Server-Side Procedures  Using SQL*Plus: -Syntax DROP PROCEDURE procedure_name

-Example SQL> DROP PROCEDURE raise_salary; Procedure dropped.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating Functions - A function is a named PL/SQL block that returns a value. - A function can be stored in the database, as a database object, for repeated execution. - A function can be called as part of an expression.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Syntax for Creating Functions CREATE [OR REPLACE] FUNCTION function_name (argument1 [mode1] datatype1, argument2 [mode2] datatype2, . . .) RETURN datatype IS|AS PL/SQL Block;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating a Function Oracle Procedure Builder

Edit

System editor

1

Text file Store in database Source code Compile

2

p-code Execute IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating a Stored Function Using SQL*Plus 

Enter the text of the CREATE FUNCTION statement in a system editor or word processor and save it as a script file (.sql extension).



From SQL*Plus, run the script file to compile the source code into p-code and store both in the database.



Invoke the function from an Oracle Server environment to determine whether it executes without error.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating a Stored Function Using SQL*Plus : Example SQL> CREATE OR REPLACE FUNCTION get_sal 2 (v_id IN emp.empno%TYPE) 3 RETURN NUMBER 4 IS 5 v_salary emp.sal%TYPE :=0; 6 BEGIN 7 SELECT sal 8 INTO v_salary 9 FROM emp 10 WHERE empno = v_id; 11 RETURN (v_salary); 12 END get_sal; 13 /

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Executing Functions

 Invoke a function as part of a PL/SQL expression.  Create a host variable to hold the returned value.  Execute the function. The host variable will be populated by the RETURN value.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Executing Functions in SQL*Plus: Example 7934

v_id

SQL> START get_salary.sql Procedure created. created SQL> VARIABLE g_salary number SQL> EXECUTE :g_salary := get_sal(7934) PL/SQL procedure successfully completed. SQL> PRINT g_salary G_SALARY -----------------1300

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Locations to Call User-Defined Functions  Select list of a SELECT command  Condition of the WHERE and HAVING clauses  CONNECT BY, START WITH, ORDER BY, and GROUP BY clauses  VALUES clauses of the INSERT command  SET clause of the UPDATE command

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Removing a Server-Side Function  Using SQL*Plus - Syntax DROP FUNCTION function_name

- Example SQL> DROP FUNCTION get_salary; Function dropped.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Comparing Procedures and Functions Procedure

Function

Execute as a PL/SQL statement

Invoke as part of an expression

No RETURN datatype

Must contain a RETURN datatype

Can return zero, one or more values

Must return a value

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Benefits of Stored Procedures and Functions  Improved performance  Improved maintenance  Improved data security and integrity

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating Packages

 Group logically related PL/SQL types, items, and subprograms  Consist of two parts:  Specification  Body  Cannot be called, parameterized, or nested  Allow Oracle8 to read multiple objects into memory at once

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Advantages of Packages

 Modularity  Easier application design  Information hiding  Added functionality  Better performance  Overloading

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Developing a Package 1 Package specification

Procedure A declaration

2 4

Package body

Procedure B definition

3

Procedure A definition

2

5

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating the Package Specification & Body Syntax CREATE [OR REPLACE] PACKAGE package_name IS | AS public type and item declarations subprogram specifications END package_name; CREATE [OR REPLACE] PACKAGE BODY package_name IS | AS private type and item declarations subprogram bodies END package_name;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Public and Private Constructs COMM_PACKAGE package Package specification

Package body

IGSI Confidential

|

G_COMM

1

RESET_COMM procedure declaration

2

VALIDATE_COMM function definition

3

RESET_COMM procedure definition

2

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating a Package Specification: Example SQL>CREATE OR REPLACE PACKAGE comm_package IS 2 g_comm NUMBER := 10; --initialized to 10 3 PROCEDURE reset_comm 4 (v_comm IN NUMBER); 5 END comm_package; 6 /

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Creating a Package Body : Example CREATE OR REPLACE PACKAGE BODY comm_package IS FUNCTION validate_comm (v_comm IN NUMBER) RETURN BOOLEAN IS v_max_comm NUMBER; BEGIN SELECT MAX (comm) INTO v_max_comm FROM emp; IF v_comm > v_max_comm THEN RETURN (FALSE); ELSE RETURN (TRUE); END IF; END validate_comm; PROCEDURE reset_comm (v_comm IN NUMBER) IS v_valid BOOLEAN; BEGIN v_valid := validate_comm (v_comm); IF v_valid = TRUE THEN g_comm := v_comm; ELSE raise_application_error (-20210, 'Invalid commission'); END IF; END reset_comm; END comm_package; /

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Invoking Package Constructs  Example 1: Invoke a function from a procedure within the same package.

CREATE OR REPLACE PACKAGE BODY comm_package IS . . . PROCEDURE reset_comm(v_comm IN NUMBER) IS v_valid BOOLEAN; BEGIN v_valid := validate_comm(v_comm); IF v_valid = TRUE THEN g_comm := v_comm; ELSE RAISE_APPLICATION_ERROR (-20210, 'Invalid comm'); END IF; END reset_comm; END comm_package;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Invoking Package Constructs Example 2: Invoke a package procedure from SQL*Plus. SQL>

EXECUTE comm_package.reset_comm(1500);

Example 3: Invoke a package procedure in a different schema. SQL>

EXECUTE scott.comm_package.reset_comm(1500);

Example 4: Invoke a package procedure in a remote database.

SQL>

EXECUTE comm_package.reset_comm@ny (1500);

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Referencing a Global Variable Within the Package Example 1 CREATE OR REPLACE PACKAGE BODY comm_package IS . . . PROCEDURE reset_comm(v_comm IN NUMBER) IS v_valid BOOLEAN; BEGIN v_valid := validate_comm(v_comm); IF v_valid = TRUE THEN g_comm := v_comm; ELSE RAISE_APPLICATION_ERROR (-20210,'Invalid comm'); END IF; END reset_comm; END comm_package;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Overloading  Allows you to use the same name for different subprograms inside a package  The formal parameters of the subprograms must differ in number, order, or datatype family  Overloaded subprograms can be placed in local or packaged subprograms

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Overloading : Example Initialize the first 50 rows in two PL/SQL tables. PROCEDURE initialize(tab OUT datetabtyp, n INTEGER) IS BEGIN FOR i in 1..n LOOP tab(i) := SYSDATE; END LOOP; END initialize; PROCEDURE initialize(tab OUT realtabtyp, n INTEGER) IS BEGIN FOR i in 1..n LOOP tab(i) := 1000; END LOOP; END initialize; IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Removing Packages To remove the package specification and the body: DROP PACKAGE package_name

To remove the package body: DROP PACKAGE BODY package_name

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Exception Handling  In PL/SQL a warning or error condition is called an exception. Exceptions can be internally defined (by the runtime system) or user-defined.  Run-time errors arise from design faults, coding mistakes, hardware failures, and many other sources. Although you cannot anticipate all possible errors, you can plan to handle certain kinds of errors meaningful to your PL/SQL program.   With PL/SQL, a mechanism called exception handling lets you "bulletproof" your program so that it can continue operating in the presence of errors.  When an error occurs, an exception is raised. That is, normal execution stops and control transfers to the exception handling part of your PL/SQL block or subprogram. Internal exceptions are raised implicitly (automatically) by the runtime system. User-defined exceptions must be raised explicitly by RAISE statements, which can also raise predefined exceptions.  To handle raised exceptions, you write separate routines called exception handlers. After an exception handler runs, the current block stops executing and the enclosing block resumes with the next statement. If there is no enclosing block, control returns to the host environment.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

A Block without Exception Section SQL> declare 2 emp_sal EMP.SAL%TYPE; 3 emp_no EMP.EMPNO%TYPE; 4 vname varchar2(10) :='&name'; 5 begin 6 select EMPNO, SAL into emp_no, emp_sal 7 from EMP1 where ENAME = vname; 8 9 if emp_sal * 1.05 > 4000 then 10 dbms_output.put_line('High Salary'); 11 else 12 update EMP set sal = sal + sal * .1 13 where ENAME=vname; 14 end if ; 15 16 dbms_output.put_line('Salary Increased'); 17 end; 18 / Enter value for name: KING old 4: vname varchar2(10) :='&name'; new 4: vname varchar2(10) :='KING'; High Salary Salary Increased PL/SQL procedure successfully completed. IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

A Block without Exception Section SQL> declare 2 emp_sal EMP.SAL%TYPE; 3 emp_no EMP.EMPNO%TYPE; 4 vname varchar2(10) :='&name'; 5 begin 6 select EMPNO, SAL into emp_no, emp_sal 7 from EMP1 where ENAME = vname; 8 9 if emp_sal * 1.05 > 4000 then 10 dbms_output.put_line('High Salary'); 11 else 12 update EMP set sal = sal + sal * .1 13 where ENAME=vname; 14 end if ; 15 16 dbms_output.put_line('Salary Increased'); 17 end; 18 / Enter value for name: JOHN old 4: vname varchar2(10) :='&name'; new 4: vname varchar2(10) :='JOHN'; declare * ERROR at line 1: ORA-01403: no data found ORA-06512: at line 6

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

A Block with Exception Section SQL> declare 2 emp_sal EMP.SAL%TYPE; 3 emp_no EMP.EMPNO%TYPE; 4 vname varchar2(10) :='&name'; 5 too_high_sal exception; 6 begin 7 select EMPNO, SAL into emp_no, emp_sal 8 from EMP1 where ENAME = vname; 9 10 if emp_sal * 1.05 > 4000 then 11 raise too_high_sal; 12 else 13 update EMP set sal = sal + sal * .1 14 where ENAME=vname; 15 end if ; 16 17 dbms_output.put_line('Salary Increased'); 18 exception 19 when no_data_found then 20 dbms_output.put_line(vname || ' Not Found'); 21 when too_high_sal then 22 dbms_output.put_line(vname || ' Already High Salary'); 23 end; 24 / Enter value for name: JOHN old 4: vname varchar2(10) :='&name'; new 4: vname varchar2(10) :='JOHN'; JOHN Not Found PL/SQL procedure successfully completed. IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Pre-defined Exception  An internal exception is raised implicitly whenever your PL/SQL program violates an Oracle rule or exceeds a system-dependent limit. Every Oracle error has a number, but exceptions must be handled by name. For example, the predefined exception NO_DATA_FOUND is raised if a SELECT INTO statement returns no rows. The table below lists some of these exceptions with their names and a short description.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

User-defined Exceptions Raising an Exception

User-defined exceptions must be raised explicitly by RAISE statements. You can place RAISE statements for a given exception anywhere within the scope of that exception. You can also raise a predefined exception explicitly. DECLARE out_of_stock EXCEPTION; number_on_hand NUMBER(4); BEGIN ... IF number_on_hand < 1 THEN RAISE out_of_stock; END IF; EXCEPTION WHEN out_of_stock THEN -- handle the error END;

IGSI Confidential

|

DECLARE acct_type INTEGER := 7; BEGIN IF acct_type NOT IN (1, 2, 3) THEN -- raise predefined exception RAISE INVALID_NUMBER; END IF; EXCEPTION WHEN INVALID_NUMBER THEN ROLLBACK; END;

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

How PL/SQL Exceptions Propagate  When an exception is raised, if PL/SQL cannot find a handler for it in the current block or subprogram, the exception propagates. That is, the exception reproduces itself in successive enclosing blocks until a handler is found or there are no more blocks to search.

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

How PL/SQL Exceptions Propagate

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

How PL/SQL Exceptions Propagate

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Associating a PL/SQL Exception with a Number  In PL/SQL, the predefined pragma EXCEPTION_INIT tells the compiler to associate an exception name with an ORACLE error number.

Declare

Associate

Declarative section

• Name the

• Code the PRAGMA

exception

IGSI Confidential

EXCEPTION_INIT

|

Wednesday, August 5, 2009

Reference Exception-handling section

• Handle the raised exception © Copyright IBM Corporation 2003

IBM Global Services

Associating a PL/SQL Exception with a Number DECLARE e_emps_remaining EXCEPTION; e_emps_remaining EXCEPTION; PRAGMA PRAGMA EXCEPTION_INIT EXCEPTION_INIT ( ( e_emps_remaining, e_emps_remaining,-2292); -2292); v_deptno dept.deptno%TYPE := &p_deptno; BEGIN DELETE FROM dept WHERE deptno = v_deptno; COMMIT; EXCEPTION WHEN e_emps_remaining e_emps_remaining THEN DBMS_OUTPUT.PUT_LINE ('Cannot remove dept ' || TO_CHAR(v_deptno) || '. Employees exist. '); END;

IGSI Confidential

|

Wednesday, August 5, 2009

1 2

3

© Copyright IBM Corporation 2003

IBM Global Services

Functions for Trapping Exceptions SQLCODE Returns the numeric value for the error code SQLERRM Returns the message associated with the error number

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Example DECLARE v_error_code v_error_message BEGIN ... EXCEPTION ... WHEN OTHERS THEN ROLLBACK; v_error_code := v_error_message

NUMBER; VARCHAR2(255);

SQLCODE ; := SQLERRM SQLERRM ;

INSERT INTO errors VALUES(v_error_code, v_error_message); END;

IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

RAISE_APPLICATION_ERROR Procedure Syntax raise_application_error (error_number, message[, {TRUE | FALSE}]);

A procedure that lets you issue user-defined error Messages from stored subprograms Called only from an executing stored subprogram Used in two different places:  Executable section  Exception section Returns error conditions to the user in a manner consistent with other Oracle Server errors IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

IBM Global Services

Example 1 Declare 2 curr_sal NUMBER; 3 vempno NUMBER := &emp_id; 4 BEGIN 5 SELECT sal INTO curr_sal FROM emp WHERE empno = vempno ; 6 IF curr_sal IS NULL THEN 7 raise_application_error(-20101, 'Salary is missing'); 8 ELSE 9 UPDATE emp SET sal = curr_sal + 500 10 WHERE empno = vempno ; 11 END IF; 12* END; SQL> / Enter value for emp_id: 7900 old 3: vempno NUMBER := &emp_id; new 3: vempno NUMBER := 7900; Declare * ERROR at line 1: ORA-20101: Salary is missing ORA-06512: at line 7 IGSI Confidential

|

Wednesday, August 5, 2009

© Copyright IBM Corporation 2003

Related Documents


More Documents from ""