Overview · What is PL/SQL · Advantages of PL/SQL · Basic Structure of a PL/SQL Block · Anonymous Block · Types of Block · Declaring a Variable · Constant · Variable Initialization · Select Statement · Execution Control · Cursor · If Statement · Basic Loop · For Loop · While Loop · Exception Handling · Procedure · Function
What is PL/SQL Increase the expressiveness of SQL, Process query results in a tuple-oriented way, Optimize combined SQL statements, Develop modular database application programs, Reuse program code, and Reduce the cost for maintaining and changing applications.
Advantages of PL/SQL Can include error handling and control structures Can be stored and used by various application programs or users Allows for tighter security by granting privileges for executing stored procedures rather than granting privileges directly on database object
Basic Structure of a PL/SQL Block · Has three sections: Declarative section Executable section Exception-handling section · Syntax: [DECLARE] BEGIN … SQL & other executable statements [EXCEPTION] END;
Structure of PL-SQL block [ ] [declare ] begin [exception ] end;
Declarative Section Identified by the DECLARE keyword Used to define variables and constants referenced in the block Variable: o Reserve a temporary storage area in memory o Manipulated without accessing a physical storage medium Constant: o Its assigned value can’t be changed during execution Forward execution: o Variable and constants must be declared before they can be referenced
Executable Section Identified by the BEGIN keyword o Mandatory o Can consist of several SQL and/or PL/SQL statements Used to access & manipulate data within the block
Exception-handling Section Identified by the EXCEPTION keyword Used to display messages or identify other actions to be taken when an error occurs Addresses errors that occur during a statement’s execution Examples: No rows returned or divide by zero errors
Types of Blocks · Anonymous block · Procedure · Function
Anonymous Block Not stored since it cannot be referenced by a name Usually embedded in an application program, stored in a script file, or manually entered when needed To perform one-time processing activities
Declaring a Variable · Reserves a temporary storage area in the computer’s memory · Every variable must have: A name A data type Form is · Variables can be initialized · Variable name can consist of up to 30 characters, numbers, or special symbols · Variable name must begin with a character · You can use naming conventions, for example v_name to represent a variable, and c_name to represent a constant.
Constants ·Variables that have a value that does not change during the execution of the block · Optional CONSTANT keyword can be used to designate a constant in the block’s declarative section
Variable Initialization Use DEFAULT keyword or (:=) assignment operator Variable must be initialized if it is assigned a NOT NULL constraint Non-numeric data types must be enclosed in single quotation marks
Variable Initialization Examples
Example Declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); begin radius := 3; area := pi*power(radius,2); insert into AREAS values (radius, area); end; / The end; line signals the end of the PL/SQL block; Depending on the tool you use, you may need to add a slash (/) to execute the PL/SQL block.
%TYPE & %ROWTYPE %TYPE Takes the data type from the table Form is. %TYPE
%TYPE & %ROWTYPE %ROWTYPE Creates a record with fields for each column of the specified table DECLARE row_variabletable %ROWTYPE; BEGIN SELECTcolumn name1, column name2, ………… INTOrow_variable FROMtable name WHEREcolumn name = variable name; The variables are then accessed as: row_variable.column name where column name is the name of a column in the table. Allows programs to adapt as the database changes
Example create table AREAS( radius number(7,2), areanumber(14,2)); create table RADIUS_VALS( radius number(7,2));
Example ( %TYPE) Declare piconstant NUMBER(9,7) := ; radi areas.radius%type; a areas.area%type ; begin radi := 4; a := pi*power(radi,2); insert into AREAS values (radi, a); end; / PL/SQL procedure successfully completed.
Example ( %ROWTYPE ) Declare pi constant NUMBER(9,7) := ; a areas%rowtype ; begin a.radius := 6; a.area := pi*power(a.radius,2); insert into AREAS values (a.radius, a.area); end; /
SELECT Statement The SELECT statement may be used in a block of code but the following example will return an error: BEGIN SELECT Cust_id FROM Customer; END; Correct form is: select into from
SELECT Statement Requires use of INTO clause to identify variable assigned to each data element Syntax: SELECT columnname [, columnname, …] INTO variablename [, variablename, …] FROM tablename WHERE condition;
SELECT Statement Example DECLARE S_Cust_id VARCHAR2(12); S_Cust_nameVARCHAR2(12); S_Cust_dobDATE; BEGIN Select Cust_id, Cust_name, Cust_dob Into S_Cust_id, S_Cust_name, S_Cust_dob From Customer Where Cust_id = 'C '; DBMS_OUTPUT.PUT_LINE('CustomerName:'|| S_Cust_name || 'Customer Date of Birth: ' || S_Cust_dob); END; /
Terminal Response SET SERVEROUTPUT ON; DBMS_OUTPUT.PUT_LINE(); Form of argument ('Salary is: ' || salary) Example: DBMS_OUTPUT.PUT_LINE('Name:‘|| fname);
Problem of previous Select It is important to ensure that the select statement retrieves at most one tuple! Otherwise it is not possible to assign the attribute values to the specified list of variables and a runtime error occurs. If the select statement retrieves more than one tuple, a cursor must be used instead. Furthermore, the data types of the specified variables must match those of the retrieved attribute values. For most data types, PL/SQL performs an automatic type conversion (e.g., from integer to real).
Cursors When a query returns multiple rows, defining a cursor allows us to » process beyond the first row returned » keep track of which row is currently being processed Cursors are defined and manipulated using » DECLARE » OPEN » FETCH » CLOSE
Declaring Cursors Syntax · Cursor name - similar to a pointer variable · There is no INTO clause · Example CURSOR IS ; CURSOR emp_cursor IS SELECT employee_id, employee_name FROM employee WHERE employee_name LIKE 'E%';
Cursors
Opening a Cursor Opens a cursor (which must be closed) Gets the query result from the database The rows returned become the cursor's current active set Sets the cursor to position before the first row. This becomes the current row. NOTE - You must use the same cursor name if you want data from that cursor. OPEN ; OPEN emp_cursor;
Fetching A Row Syntax Moves the cursor to the next row in the current active set Assigns values to the host variables FETCH INTO ; FETCH emp_cursor INTO e_id, e_name;
Closing the Cursor Closes the cursor (which must be open) There is no longer an active set Reopening the same cursor will reset it to point to the beginning of the returned table CLOSE ; CLOSE emp_cursor;
Fetching A Row
CURSOR Example DECLARE CURSOR emp_cursor IS SELECT employee_id, employee_name FROM employee WHERE employee_name LIKE 'E%'; emp_val emp_cursor%ROWTYPE; BEGIN OPEN emp_cursor; FETCH emp_cursor INTO emp_val; DBMS_OUTPUT.PUT_LINE(emp_val.employee_id); CLOSE emp_cursor; END; /
Example create table AREAS( radius number(7,2), areanumber(14,2)); create table RADIUS_VALS( radius number(7,2));
Example Declare Piconstant NUMBER(9,7) := ; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; begin open rad_cursor; fetch rad_cursor into rad_val; area := pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); close rad_cursor; end; /
Explanation When the rad_cursor cursor is opened, the query declared for that cursor is executed and the records to be returned are identified. Next, records are fetched from the cursor. In the Declarations section, the rad_val variable is declared to anchor its datatypes to the rad _cursor cursor. When you fetch a record from the cursor into the rad_val variable, you can still address each column value selected via the cursor’s query. When the cursor’s data is no longer needed, you can close the cursor.
Example You can even base %TYPE definitions on cursors. cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; rad_val_radius rad_val.Radius%TYPE; In the example, the rad_val variable inherits the datatypes of the result set of the rad_cursor cursor. The rad_val_radius variable inherits the datatype of the Radius column within the rad_val variable
Cursor Properties Cursors have four attributes that can be used In program: –%FOUND, %NOTFOUND : a record can/cannot be fetched from the cursor –%ISOPEN : the cursor has been opened –%ROWCOUNT : the number of rows fetched from the cursor so far
Execution Control Decision: IF statement executes statements based on a condition Loops: Basic loop Executes statements until condition in EXIT clause is TRUE FOR loop Uses counter WHILE loop Executes statements until condition is FALSE
IF Statement Syntax: IF THEN ELSIF THEN ELSE END IF;
Flow Chart of IF-THEN-ELSE
IF Statement
Basic Loop Syntax: LOOP Statements; EXIT [WHEN condition]; END LOOP;
Flow chart of Loop
Basic Loop
FOR Loop Syntax: FOR counter IN [reverse] lower_limit.. upper_limit LOOP sequence of statements ; END LOOP;
For Loop The loop counter is declared implicitly. The scope of the loop counter is only the for loop. It overrides the scope of any variable having the same name outside the loop. Inside the for loop, counter can be referenced like a constant. counter may appear in expressions, but one cannot assign a value to counter.
For Loop Using the keyword reverse causes the iteration to proceed downwards from the higher bound to the lower bound. A loop can be named. Naming a loop is useful whenever loops are nested and inner loops are completed unconditionally using the exit ; statement
Flow Chart of For Loop
FOR Loop
WHILE Loop Syntax: WHILE condition LOOP Statements; END LOOP;
Flow Chart of While Loop
WHILE Loop
Simple Loops declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); begin radius := 3; Loop area := pi*power(radius,2); insert into AREAS values (radius, area); radius := radius+1; exit when area >100; end loop; end;
For Loops declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); begin /* Specify the criteria for the number of loop executions. */ for radius in 1..7 loop area := pi*power(radius,2); insert into AREAS values (radius, area); /* Signal the end of the loop. */ end loop; end; /
For Loops declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); begin for radius in reverse 7..1 loop area := pi*power(radius,2); insert into AREAS values (radius, area); end loop; end; /
Simple While Loop declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); begin radius := 3; while area<100 loop area := pi*power(radius,2); DBMS_OUTPUT.PUT_LINE(concat('Radius is:',radius)); DBMS_OUTPUT.PUT_LINE(concat('Areas is:', area)); radius := radius+1; end loop; end; /
Nested Loops Any type of loop can be nested inside another loop Execution of the inner loop must becompleted before control is returned to the outer loop
Nested Loops
Continue You can use the continue statement within loops to exit the current iteration of the loop and transfer control to the next iteration. For example, if you iterate through a set of counter values, you can skip specific values without exiting the loop entirely. The two forms of the continue statement are continue and continue when. The when portion provides the condition to be evaluated. If the condition is true, the current iteration of the loop will complete and control will pass to the next iteration.
Continue declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); begin radius := 1; loop if radius < 5 then continue; end if; area := pi*power(radius,2); insert into AREAS values (radius, area); radius := radius+1; exit when area >100; end loop; end;
Continue when declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); begin radius := 1; loop continue when radius < 5; area := pi*power(radius,2); insert into AREAS values (radius, area); radius := radius+1; exit when area >100; end loop; end;
Case You can use case statements to control the branching logic within your PL/SQL blocks. For example, you can use case statements to assign values conditionally or to transform values prior to inserting them. case CategoryName when ‘SCIFI' then ‘Science Fiction' when 'ADV' then 'Adventure' when ‘ANIM' then 'Animation ' else CASE_NOT_FOUND end The keyword case begins the clause. The when clauses are evaluated sequentially. The else keyword within the case clause works similarly to the else keyword within an if - then clause.
Simple Cursor Loops You can use the attributes of a cursor—such as whether or not any rows are left to be fetched—as the exit criteria for a loop. In the following examples, a cursor is executed until no more rows are returned by the query. Before a cursor can be used, it must be opened using the open statement The associated select statement then is processed and the cursor references the first selected tuple. Selected tuples then can be processed one tuple at a time using the fetch command
Simple Cursor Loops The fetch command assigns the selected attribute values of the current tuple to the list of variables. After the fetch command, the cursor advances to the next tuple in the result set. Note that the variables in the list must have the same data types as the selected values. After all tuples have been processed, the close command is used to disable the cursor. Each loop can be completed unconditionally using the exit clause: exit [ ] [when ]
Simple Cursor Loops Using exit without a block label causes the completion of the loop that contains the exit statement The condition refers to a cursor. To determine the status of the cursor, the cursor’s attributes are checked. Cursors have four attributes you can use in your program: %FOUND- A record can be fetched from the cursor. %NOTFOUND- No more records can be fetched from the cursor. %ISOPEN - The cursor has been opened. %ROWCOUNT - The number of rows fetched from the cursor so far. The %FOUND, %NOTFOUND, and %ISOPEN cursor attributes are Booleans; they are set to either TRUE or FALSE. You can evaluate their settings without explicitly matching them to values of TRUE or FALSE.
Simple Cursor Loops DECLARE CURSOR emp_cursor IS SELECT employee_id, employee_name, sal FROM employee WHERE employee_name LIKE 'E%'; emp_val emp_cursor%ROWTYPE; emp_sal emp_cursor.sal%TYPE BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO emp_val; EXIT WHEN emp_cursor%NOTFOUND; emp_sal := emp_val.sal; DBMS_OUTPUT.PUT_LINE(emp_val.employee_id); END LOOP; CLOSE emp_cursor; END; /
Simple Cursor Loop Declare pi constant NUMBER(9,7) := ; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; rad_val rad_cursor%ROWTYPE; begin open rad_cursor; loop fetch rad_cursor into rad_val; exit when rad_cursor%NOTFOUND; area := pi*power(rad_val.radius,2); DBMS_OUTPUT.PUT_LINE(concat('Radius is:',rad_val.radius)); DBMS_OUTPUT.PUT_LINE(concat('Areas is:', area)); end loop; close rad_cursor; End;
Simple Cursor Loops In the example above, %NOTFOUND is a predicate that evaluates to false if the most recent fetch command has read a tuple. The value of %NOTFOUND is null before the first tuple is fetched. The predicate evaluates to true if the most recent fetch failed to return a tuple, and false otherwise. %FOUND is the logical opposite of %NOTFOUND.
Cursor FOR Loops A Cursor FOR loop uses the results of a query to dynamically determine the number of times the loop is executed. In a Cursor FOR loop, the opening, fetching, and closing of cursors is performed implicitly; You do not need to explicitly specify these actions. Cursor for loops can be used to simplify the usage of a cursor
Cursor FOR Loops DECLARE CURSOR emp_cursor IS SELECT employee_id, employee_name, sal FROM employee WHERE employee_name LIKE 'E%'; BEGIN for emp_val in emp_cursor LOOP emp_sal := emp_val.sal; DBMS_OUTPUT.PUT_LINE(emp_val.employee_id); END LOOP; END; / Fetches the current row to emp_val
Cursor FOR Loops In a Cursor FOR Loop, there is no open or fetch command. A record suitable to store a tuple fetched by the cursor is implicitly declared. Note that emp_val is not explicitly declared in the block. Furthermore, this loop implicitly performs a fetch at each iteration as well as an open before the loop is entered and a close after the loop is left. If at an iteration no tuple has been fetched, the loop is automatically terminated without an exit.
Cursor FOR Loops The command for emp_val in emp_cursor implicitly opens the emp_cursor cursor and fetches a value into the emp_val variable. When no more records are in the cursor, the loop is exited and the cursor is closed. In a Cursor FOR loop, there is no need for a close command. It is even possible to specify a query instead of in a for loop: -for sal_rec in (select SAL + COMM total from EMP) loop -... ; -end loop;
Cursor FOR Loops Except data definition language commands such as create table, all types of SQL statements: delete, insert, update, and commit can be used in PL/SQL blocks Note that in PL/SQL only select statements of the type select into are allowed, i.e., selected attribute values can only be assigned to variables (unless the select statement is used in a subquery). The usage of select statements as in SQL leads to a syntax error.
Cursor For Loop declare pi constant NUMBER(9,7) := ; area NUMBER(14,2); cursor rad_cursor is select * from RADIUS_VALS; begin /* If a record can be fetched from the cursor, then fetch it into the rad_val variable. If no rows can be fetched, then skip the loop. */ for rad_val in rad_cursor loop area := pi*power(rad_val.radius,2); DBMS_OUTPUT.PUT_LINE(concat('Radius is:',rad_val.radius)); DBMS_OUTPUT.PUT_LINE(concat('Areas is:', area)); end loop; end; /
Cursor Update If some tuples selected by the cursor will be modified in the PL/SQL block, the clause for update [( )] has to be added at the end of the cursor declaration. In this case selected tuples are locked and cannot be accessed by other users until a commit has been issued. If update or delete statements are used in combination with a cursor, these commands can be restricted to currently fetched tuple. In these cases the clause where current of is added as shown in the following example.
Cursor Update (Error!) All employees having ’KING’ as their manager get a 5% salary increase. Note that the record emp_rec is implicitly defined. //check below Declare manager EMP.MGR%TYPE; cursor emp_cur (mgr no number) is select SAL from EMP where MGR = mgr no for update of SAL; Begin for emp_rec in emp cur(manager) loop select EMPNO into manager from EMP where ENAME = ’KING’; update EMP set SAL = emp_rec.sal * 1.05 where current of emp_cur; end loop; commit; end;
Procedure Sophisticated business rules and application logic can be stored as procedures within Oracle You may group procedures and other PL/SQL commands into packages. You may experience performance gains when using procedures for two reasons: The processing of complex business rules may be performed within the database—and therefore by the server. Because the procedural code is stored within the database and is fairly static, you may also benefit from the reuse of the same queries within the database
Procedure · Also called “Stored Procedures” · Named block · Can process several variables · Returns no values · Interacts with application program using IN, OUT, or INOUT parameters Valid parameters include all data types. However, for char, varchar2, and number no length and scale, respectively, can be specified. For example, the parameter number (6) results in a compile error and must be replaced by number
Procedure Basic Syntax CREATE [OR REPLACE] PROCEDURE name [( argument [IN|OUT|IN OUT] datatype [{, argument [IN|OUT|IN OUT] datatype }] )] AS /* declaration section */ BEGIN /* executable section - required*/ EXCEPTION /* error handling statements */ END; /
Some Details Parameter direction: The optional clauses IN, OUT, and IN OUT specify the way in which the parameter is used. The default mode is IN » IN (default) : means that the parameter can be referenced inside the procedure body, but it cannot be changed » OUT: means that a value can be assigned to the parameter in the body, but the parameter’s value cannot be referenced. The OUT qualifier signifies that the procedure passes a value back to the caller through this argument » IN OUT: allows both assigning values to the parameter and referencing the parameter.
Some Details IN OUT: A value must be specified for this argument when the procedure is called, and the procedure will return a value to the caller via this argument Executing procedures » EXECUTE ( ) » EXECUTE ; A procedure can be deleted using the command drop procedure drop function
Procedure Example Create Procedure Insert_Customer(customerid IN varchar2) As BEGIN insert into customer values(customerid,Null, Null, Null, Null); END; / Execute Insert_Customer(‘c_67’);
Function · Named block that is stored on the Oracle server · Accepts zero or more input parameters · Returns one value
Function Basic Syntax CREATE [OR REPLACE] FUNCTION name [( argument datatype [{, argument datatype}] )] RETURN datatype AS /* declaration section */ BEGIN /* executable section - required*/ EXCEPTION /* error handling statements */ END; /
Function Example CREATE OR REPLACE FUNCTION getBDate (customerid VARCHAR2) RETURN DATE AS v_bdate customer.cust_dob%TYPE; BEGIN SELECT cust_dob INTO v_bdate FROM customer WHERE cust_id = customerid; RETURN v_bdate; END; / select getBDate( 'C ') ) from dual;
Function Example CREATE OR REPLACE PROCEDURE show_date(c_id VARCHAR2) AS BEGIN DBMS_OUTPUT.PUT_LINE(getBDate(c_id)); END; / Execute show_date('C ');
Exception Handling A PL/SQL block may contain statements that specify Exception handling routines. Each error or warning during the execution of a PL/SQL block raises an exception. One can distinguish between two types of exceptions: · system defined exceptions · user defined exceptions
S ystem Defined Exceptions System defined exceptions are always automatically raised whenever corresponding errors or warnings occur.
User Defined Exceptions User defined exceptions, in contrast, must be raised explicitly in a sequence of statements using raise. After the keyword exception at the end of a block, user defined exception handling routines are implemented. An implementation has the pattern when then ;
Exception Handling declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); some_variable NUMBER(14,2); begin radius := 3; loop some_variable := 1/(radius-4); area := pi*power(radius,2); insert into AREAS values (radius, area); radius := radius+1; exit when area >100; end loop; end;
User Defined Exceptions Because the calculation for some_variable involves division, you may encounter a situation in which the calculation attempts to divide by zero—an error condition The second time through the loop, the radius variable has a value of 4—and the calculation for some_variable encounters an error: ERROR at line 1: ORA-01476: divisor is equal to zero ORA-06512: at line 9 Because an error was encountered, the first row inserted into AREAS is rolled back, and the PL/SQL block terminates. You can modify the processing of the error condition by adding an Exception Handling section to the PL/SQL block, as shown next
Exception Handling declare pi constant NUMBER(9,7) := ; radius INTEGER(5); area NUMBER(14,2); some_variable NUMBER(14,2); begin radius := 3; loop some_variable := 1/(radius-4); area := pi*power(radius,2); insert into AREAS values (radius, area); radius := radius+1; exit when area >100; end loop; exception when ZERO_DIVIDE then insert into AREAS values (0,0); end;
Exception Handling declare emp_salNUMBER(10,3); Emp_noVARCHAR2(12); too_high_sal exception; begin select EMPLOYEE_ID, SALARY into emp_no, emp_sal from EMPLOYEE where EMPLOYEE_NAME = ’E_Y’; if emp_sal * 1.05 > 2000 then raise too_high_sal; end if; exception when NO_DATA_FOUND then DBMS_OUTPUT.PUT_LINE(‘No data found’); when too_high_sal then DBMS_OUTPUT.PUT_LINE(‘High Salary’); end; /
Exception Handling When the PL/SQL block encounters an error, it scans the Exception Handling section for the defined exceptions. After the keyword when a list of exception names, connected with or can be specified. In addition to the system-defined exceptions and user defined exceptions, you can use the when others clause to address all exceptions not defined within your Exception Handling section. This introduces the default exception handling routine, for example, a rollback.
Exception Handling It is also possible to use procedure raise_application_error. This procedure has two parameters and. is a negative integer defined by the user and must range between and is a string with a length up to 2048 characters. If the procedure raise application error called from a PL/SQL block, processing the PL/SQL block terminates and all database modifications are undone, that is, an implicit rollback is performed in addition to displaying the error message.
Exception Handling declare emp_salNUMBER(10,3); Emp_noVARCHAR2(12); begin select EMPLOYEE_ID, SALARY into emp_no, emp_sal from EMPLOYEE where EMPLOYEE_NAME = ’E_Y’; if emp_sal * 1.05 > 2000 then raise_application_error(-20010, ’Salary is too high for ’ || to_char(Emp no) ); end if; end; /
Exception Handling The concatenation operator “||” can be used to concatenate single strings to one string. In order to display numeric variables, these variables must be converted to strings using the function to_char. Once an exception is encountered, you cannot return to your normal flow of command processing within the Executable Commands section. If you need to maintain control within the Executable Commands section, you should use if conditions to test for possible exceptions before they are encountered by the program, or create a nested block with its own local exception handling.
Compilation Errors Loading a procedure or function may cause compilation errors. SHOW ERRORS; gives the errors To get rid of procedures or functions: DROP PROCEDURE ; DROP FUNCTION ;
Debugging PL/SQL The SQL*Plus show errors command displays all the errors associated with the most recently created procedural object. This command checks the USER_ERRORS data dictionary view for the errors associated with the most recent compilation attempt for that object. Show errors displays the line and column number for each error, as well as the text of the error message. To view errors associated with previously created procedural objects, you may query USER_ERRORS directly
Debugging PL/SQL If any errors were encountered during the creation of the OVERDUE_CHARGES function, the lines in the code that resulted in the error conditions would be returned by the query. select Line, /*Line number of the error. */ Position, /*Column number of the error.*/ Text /*Text of the error message.*/ from USER_ERRORS where Name = 'OVERDUE_CHARGES' and Type = 'FUNCTION' order by Sequence; Valid values for the Type column are VIEW, PROCEDURE, PACKAGE, FUNCTION, and PACKAGE BODY
Debugging PL/SQL In addition to the debugging information provided by the show errors command, you may use the DBMS_OUTPUT package, It is automatically installed when you create an Oracle database PUT Puts multiple outputs on the same line PUT_LINE Puts each output on a separate line NEW_LINE Used with PUT; signals the end of the current output line To track the variable’s value, you may use a command similar to the one shown DBMS_OUTPUT.PUT_LINE ('Owed:'||Owed_Amount);
Viewing Source Code of Procedure The source code for existing procedures, functions, packages, and package bodies can be queried from the following data dictionary views: ○ USER_SOURCE For procedural objects owned by the user ○ ALL_SOURCE For procedural objects owned by the user or to which the user has been granted access ○ DBA_SOURCE For all procedural objects in the database Select information from the USER_SOURCE view via a query select Text from USER_SOURCE where Name = 'NEW_BOOK' and Type = 'PROCEDURE' order by Line;
Output of above query is: TEXT procedure NEW_BOOK (aTitle IN VARCHAR2, aPublisher IN VARCHAR2, aCategoryName IN VARCHAR2) as begin insert into BOOKSHELF (Title, Publisher, CategoryName, Rating) values (aTitle, aPublisher, aCategoryName, NULL); delete from BOOK_ORDER where Title = aTitle; end; ○ the USER_SOURCE view contains one record for each line of the NEW_BOOK procedure so should be ordered by with Line.
Compiling PL/SQL Oracle compiles procedural objects when they are created. Procedural objects may become invalid if the database objects they reference change. The next time the procedural objects are executed, they will be recompiled by the database. You can avoid this run-time compiling—and the performance degradation it may cause—by explicitly recompiling the procedures, functions, and packages. To recompile a procedure, use the alter procedure command, as shown in the following listing. The compile clause is the only valid option for this command. Alter function/procedure OVERDUE_CHARGES compile;
Packages It is essential for a good programming style that logically related blocks, procedures, and functions are combined into modules Each module then provides an interface which allows users and designers to utilize the implemented functionality. PL/SQL supports the concept of modularization by which modules and other constructs can be organized into packages. A package consists of a package specification and a package body. The package specification defines the interface that is visible for application programmers, and the package body implements the package specification
Packages When creating packages, the package specification and the package body are created separately. Thus, there are two commands to use: create package for the package specification, and create package body for the package body. Both of these commands require that you have the CREATE PROCEDURE system privilege. If the package is to be created in a schema other than your own, then you must have the CREATE ANY PROCEDURE system privilege
Packages Here is the syntax for creating package specifications: create [or replace] package [ user. ] package [authid {definer | current_user} ] {is | as} package specification ; A package specification consists of the list of functions, procedures, variables, constants, cursors, and exceptions that will be available to users of the package. A package body contains the blocks and specifications for all of the public objects listed in the package specification. The package body may include objects that are not listed in the package specification; such objects are said to be private and are not available to users of the package. Private objects may only be called by other objects within the same package body.
Packages A procedure or function implemented in a package can be called from other procedures and functions using the statement. [( )]. Additional functions, procedures, exceptions, variables, cursors, and constants may be defined within the package body, but they will not be available to the public unless they have been declared within the package specification (via the create package command). execute BOOK_INVENTORY.NEW_BOOK('ONCE REMOVED');
Packages If a user has been granted the EXECUTE privilege on a package, then that user can access any of the public objects that are declared in the package specification. Packages are groups of procedures, functions, variables, and SQL statements grouped together into a single unit. To execute a procedure within a package, you must first list the package name, and then list the procedure name, as shown previously Execute BOOK_INVENTORY.NEW_BOOK('ONCE REMOVED');
Packages Packages allow multiple procedures to use the same variables and cursors. Procedures within packages may be either available to the public (as is the NEW_BOOK procedure in the prior example) or private, in which case they are only accessible via commands from within the package (such as calls from other procedures). Packages may also include commands that are to be executed each time the package is called, regardless of the procedure or function called within the package. Thus, packages not only group procedures but also give you the ability to execute commands that are not procedure specific.
Packages Oracle offers several predefined packages and procedures that can be used by database users and application developers. A set of very useful procedures is implemented in the package DBMS_OUTPUT. Procedure DBMS_OUTPUT.ENABLE DBMS_OUTPUT.DISABLE DBMS_OUTPUT.PUT( ) DBMS_OUTPUT.PUT LINE( ) DBMS_OUTPUT.NEW
THANK YOU