Oracle PL/SQL Training Agenda • • • • • • • • • • Course environment setup Database Tools – SQL Developer DBMS Concepts PL/SQL Language features DECLARE Clause BEGIN Clause EXCEPTION Clause Cursors Nested Blocks Subprograms • • • • Stored Procedures Functions Packages Triggers Environment Setup • WorkStation Setup • System Requirements • SQL Developer setup • Setup Sample Data Models Introduction to DBMS Concepts RDBMS Concepts • RDBMS stands for Relational Database Management System. RDBMS is the basis for SQL, • and for all modern database systems like MS SQL Server, IBM DB2, Oracle, MySQL, and Microsoft Access. • A Relational database management system (RDBMS) is a database management system • (DBMS) that is based on the relational model as introduced by E. F. Codd. 5 Terminology in RDBMS • What is a Table • Rows-Record • Columns-Fields • NULL Value • Objects – Logical and Physical 6 SQL Constraints • Constraints are the rules enforced on data columns on a table. These are used to limit the type of data that can go into a table. This ensures the accuracy and reliability of the data in the database. • Constraints can either be column level or table level. • NOT NULL Constraint: Ensures that a column cannot have a NULL value. • • • • • DEFAULT Constraint: Provides a default value for a column when none is specified. UNIQUE Constraint: Ensures that all the values in a column are different. PRIMARY Key: Uniquely identifies each row/record in a database table. FOREIGN Key: Uniquely identifies a row/record in any another database table. INDEX: Used to create and retrieve data from the database very quickly. 7 Data Integrity • The following categories of data integrity exist with each RDBMS: • Entity Integrity: There are no duplicate rows in a table. • Domain Integrity: Enforces valid entries for a given column by restricting the type, the format, or the range of values. • Referential integrity: Rows cannot be deleted, which are used by other records. • Database Normalization - is the process of efficiently organizing data in a database. There are two reasons of this normalization process: • Eliminating redundant data. For example, storing the same data in more than one table. • Ensuring data dependencies make sense. 8 What is SQL ? • SQL is Structured Query Language, which is a computer language for storing, manipulating and retrieving data stored in a relational database. • SQL is the standard language for Relational Database System. All the Relational Database • Management Systems (RDMS) like MySQL, MS Access, Oracle, Sybase, Informix, Postgres and SQL Server use SQL as their standard database language. • Also, they are using different dialects, such as: • MS SQL Server using T-SQL, • Oracle using PL/SQL 9 SQL Processing • When you are executing an SQL command for any RDBMS, the system determines the best way to carry out your request and SQL engine figures out how to interpret the task. • There are various components included in this process. 10 SQL Commands • The standard SQL commands to interact with relational databases are CREATE, SELECT,INSERT, UPDATE, DELETE and DROP. • These commands can be classified into the following groups based on their nature: • DATA DEFINITION LANGUAGE • DATA MANIPULATION LANGUAGE • DATA CONTROL LANGUAGE 11 Commands Description • DDL - Data Definition Language • CREATE Creates a new table, a view of a table, or other object in the database. • ALTER Modifies an existing database object, such as a table. • DROP Deletes an entire table, a view of a table or other objects in the database. • DML - Data Manipulation Language • • • • SELECT Retrieves certain records from one or more tables. INSERT Creates a record. UPDATE Modifies records. DELETE Deletes records. • DCL - Data Control Language • GRANT gives a privilege to user. • REVOKE takes back privileges granted from user. 12 Various Syntax in SQL • SQL SELECT Statement • SELECT column1, column2....columnN FROM table_name; • SQL DISTINCT Clause • SELECT DISTINCT column1, column2....columnN FROM table_name; • SQL WHERE Clause • SELECT column1, column2....columnN FROM table_name WHERE CONDITION; • SQL AND/OR Clause • SELECT column1, column2....columnN FROM table_name WHERE CONDITION-1 {AND|OR} CONDITION-2; 13 Syntax Contd. • SQL IN Clause • SELECT column1, column2....columnN FROM table_name WHERE column_name IN (val-1, val-2,...val-N); • SQL BETWEEN Clause • SELECT column1, column2....columnN FROM table_name WHERE column_name BETWEEN val-1 AND val-2; • SQL LIKE Clause • SELECT column1, column2....columnN FROM table_name WHERE column_name LIKE { PATTERN }; • SQL ORDER BY Clause • SELECT column1, column2....columnN FROM table_name WHERE CONDITION ORDER BY column_name {ASC|DESC}; 14 DDL Commands • SQL CREATE TABLE Statement CREATE TABLE table_name( column1 datatype, column2 datatype, column3 datatype, ..... columnN datatype, PRIMARY KEY( one or more columns ) ); • SQL DROP TABLE Statement • DROP TABLE table_name; • SQL TRUNCATE TABLE Statement • TRUNCATE TABLE table_name; • SQL ALTER TABLE Statement • ALTER TABLE table_name {ADD|DROP|MODIFY} column_name {data_type}; 15 DML Commands • SQL DESC Statement • DESC table_name; • SQL INSERT INTO Statement • INSERT INTO table_name( column1, column2....columnN) VALUES ( value1, value2....valueN); • SQL UPDATE Statement • UPDATE table_name SET column1 = value1, column2 = value2....columnN=valueN [ WHERE CONDITION ]; • SQL DELETE Statement • DELETE FROM table_name WHERE {CONDITION}; 16 DCL Commands • SQL COMMIT Statement • COMMIT; • SQL ROLLBACK Statement • ROLLBACK; 17 Available SQL Data Types • When a variable is declared it must have a data type specified. • The following types are known as scalar data. types. • Scalar simply means a single value. Integer Data Types • Integer Data types only allow whole numbers. Data Type Definition Rules and Features BINARY_ INTEGER or PLS_INTEGER Signed Integer ±2G More efficient than NUMBER. Should be used if values will be integer. SIMPLE_ INTEGER Signed Integer ±2G Only available in Oracle 11g and later. Better performance than PLS_INTEGER. Integer Data Subtypes • Data types have subtypes that change the overflow dynamics of the type. BINARY_ INTEGER Subtype Definition Rules and Features NATURAL Range of 0 to 2G Uses the same rules as PLS_INTEGER, but no values less than 0. POSITIVE Range of 1 to 2G Uses the same rules as PLS_INTEGER, but no values less than 1. Floating Point Data Types • Data types allow for decimals. Data Type Definition Rules and Features BINARY_ FLOAT Binary data type for 32-bit singleprecision float Binary data types offer more precision than NUMBER(). Also supports infinity and NaN. BINARY_ DOUBLE Binary data type for 64-bit double precision Perfect for scientific computing applications. NUMBER (precision,scale) Numbers with Precision 1 to 38 Scale -84 to 127 Can be integer or floating point, but will operate slower than the types identified above. Character Data Types • Data types allow for numbers and text. Data Type Definition Rules and Features CHAR(n) Fixed length character data from 1 to 32,767 May map to either CHAR or LONG database columns. VARCHAR2(n) Varying length character data from 1 to 32,767 May map to either VARCHAR2 or LONG database columns. Predefined Data Types • Data types allow for different value types and more control. Data Type Definition Rules and Features ROWID (obsolete) Database row ID object Identifies a physical row in a table. UROWID Physical or Logical row ID Identifies a physical or logical row in a table. BOOLEAN Only values of True/False/Null Useful for conditional testing. DATE Date/Time from 4712 BC to 4712 AD Same rules that apply to database column. SQL Comparison Operators • Operator = != <> > Description Checks if the values of two operands are equal or not, if yes then condition becomes true. Checks if the values of two operands are equal or not if values are equal then condition becomes true. Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. 24 < >= <= !< !> Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. Checks if the value of left operand is not less than the value of right operand, if yes then condition becomes true. Checks if the value of left operand is not greater than the value of right operand, if yes then condition becomes true. 25 SQL Logical Operators Operator • ALL • AND • ANY • BETWEEN Description The ALL operator is used to compare a value to all values in another value set. The AND operator allows the existence of multiple conditions in an SQL statement's WHERE clause. The ANY operator is used to compare a value to any applicable value in the list as per the condition. The BETWEEN operator is used to search for values that are within a set of values, given the minimum value and the 26 maximum value. • EXISTS The EXISTS operator is used to search for the presence of a row in a specified table that meets a certain criterion. • IN The IN operator is used to compare a value to a list of literal values that have been specified. • LIKE The LIKE operator is used to compare a value to similar values using wildcard operators. • NOT The NOT operator reverses the meaning of the logical operator with which it is used. Eg: NOT EXISTS, NOT BETWEEN, NOT IN, etc. This is a negate operator. • OR The OR operator is used to combine multiple conditions in an SQL statement's WHERE clause. 27 • IS NULL The NULL operator is used to compare a value with a NULL value. • UNIQUE The UNIQUE operator searches every row of a specified table for uniqueness (no duplicates). 28 PL/SQL Language Features PL/SQL Language features • PL/SQL Program Deployment • Executions • Output the result - Set Serveroutput on • Structure in PL/SQL Block • PL/SQL instructions are contained within units known as ‘blocks’ Language Syntax Rules • Commenting the code using the inline comment markers ‘--’ • Using the multi-line comment block using the begin marker ‘/*’ and end marker ‘*/’ • Only one PL/SQL statement per line • All execution statements will end with semi-colon(;) Object Name Rules When selecting a name for a declared object, there are some rules you must follow: • Maximum length is 30 characters. • The first character must be a letter. • The following table outlines characters that are legal and illegal. Legal Illegal $ & # - (dash) _ (underscore) / (space) The DECLARE Clause • About the DECLARE Clause • Available Data Types • DECLARE Simple Types • DECLARE Complex Types • • • • • %Type %RowType Record Type…Table Type…Record Extended User-Defined Types DECLARE Clause Objects The DECLARE Clause is used to define (declare) internal program objects, such as variables. • The following are among PL/SQL objects Object Explanation Variable An element internal to the program that can hold and modify values. Boolean A simple type containing TRUE/FALSE/NULL Constant Similar to a variable, but cannot be changed. Record Complex object that matches the structure of a table within the database yet holds a single record. DECLARE Clause Objects Object Explanation Table Complex object that matches the structure of a table within the database. User-defined type A type that uses a combination of the predefined objects to create a new type unique to the program. DECLARE --Define variables Empname VARCHAR2(20); EmpSal NUMBER(6); EmpDOB DATE; BEGIN … END; Declare Simple Types • In addition to declaring a variable with the name and type, other options exist. • Setting the default value • Ensuring the variables are NOT NULL • Declaring a CONSTANT value Setting the Default Value • When setting a value to a variable, you must use the assignment ‘:=‘ operator. • If an assignment is not made, variables will default to NULL. DECLARE --Definitions are the same nEmpSalary NUMBER(6) := 25000; nEmpSal NUMBER(6) DEFAULT 25000; BEGIN … END; Setting Default Values by Type The data type dictates what values can be entered. • Boolean values allow for NULL/TRUE/FALSE only. DECLARE --Defining a Boolean variable bEndOfLoop BOOLEAN := FALSE; BEGIN … END; Declare Variables NOT NULL • Similar to the database constraint, you may apply the NOT NULL variable constraint to a declaration. • If the PL/SQL script attempts to set the variable to NULL, an exception is generated. • You must set an initial value to avoid violating the rule. DECLARE --Defining a NOT NULL variable nDefaultDNO NUMBER(2) NOT NULL := 10; BEGIN … END; Declare Constants • Constants are similar to variables, except they cannot be changed. • Must use the CONSTANT keyword before the type declaration. DECLARE --Defining a constant nMinSalary CONSTANT NUMBER(6) := 20000; nMaxSalary CONSTANT NUMBER(6) := 90000; BEGIN … END; See it in action Declare Complex Types • PL/SQL is tightly integrated with the Oracle database. • %TYPE • %ROWTYPE • PL/SQL also supports advanced and object-oriented programming structures. • TYPE…TABLE • TYPE…RECORD %TYPE Variable data types may be dynamically and automatically matched to any column within the Oracle table. DECLARE x_salary BEGIN …. Number(6) employee.salary%TYPE; Employee table SSN CHAR(9) … Sex CHAR(1) Salary NUMBER(6) DNO NUMBER(2) 123456789 M 30000 5 345345345 F 25000 5 888665555 M 55000 1 %TYPE Referencing a Schema • You may wish to base a data type on an object from a different schema. DECLARE --Define variables x_Lname smith.employee.lname%TYPE; x_Salary smith.employee.salary%TYPE; BEGIN … END; Maintain Internal Consistency Another means of keeping declarations consistent and adaptable, you can tie data types to another variable. DECLARE --Define variables x_MinSalary employee.salary%TYPE; x_AvgSalary x_MinSalary%TYPE; x_MaxSalary x_MinSalary%TYPE; BEGIN … END; See it in action %ROWTYPE Record %ROWTYPE is a complex type that defines a record matching the names and data types of an entire table or view. . DECLARE empRec BEGIN …. employee%ROWTYPE; Employee table SSN CHAR(9) … Sex CHAR(1) Salary NUMBER(6) DNO NUMBER(2) 123456789 M 30000 5 345345345 F 25000 5 888665555 M 55000 1 %ROWTYPE Example DECLARE --Declare variables rowEmp1 employee%ROWTYPE; rowEmp2 employee%ROWTYPE; BEGIN --Fill the fields rowEmp1.lname := 'Doe'; rowEmp1.fname := 'John'; rowEmp2.lname := 'Doe'; rowEmp2.fname := 'Jane'; … See it in action TYPE…TABLE • TABLE types are used to create single-dimensional tables. • These are useful when storing arrays of values retrieved from the database. Employee.SSN%TYPE Binary_Integer 123456789 1 345345345 2 888665555 3 987654321 4 453453453 5 Steps to Define a Table • Defining a Table is a two step process. • The User-Defined table must be declared. • Reference the user-defined type. DECLARE --Declare variables TYPE EmpSSNarray IS TABLE of employee.ssn%TYPE INDEX BY SIMPLE_INTEGER; ManagementList EmpSSNarray; WorkerList EmpSSNarray; … See it in action TYPE…RECORD • The RECORD user-defined data type allows more flexibility than the %ROWTYPE. • %ROWTYPE must match an existing table. • RECORD allows any combination of data types. Steps to Define a RECORD • Defining a Record is a two step process. • The User-Defined record must be declared. • Reference the user-defined type. DECLARE --Declare variables TYPE EmpRecord IS RECORD (ssn Lname Bonus ); ActiveEmp InactiveEmp … employee.ssn%TYPE, employee.lname%TYPE, NUMBER(6) EmpRecord; EmpRecord; See it in action User-Defined Types • Complex user-defined types may be defined which nest several levels within a hierarchy. • For example, an employee bonus might be more than just payment of a sum of money • Cash payment • Use of company car • Extra vacation weeks Example of User-Defined Type DECLARE --Simple type declaration TYPE BonusCompensation IS RECORD (CashPayment CompanyCar VacationWeeks ); --Extended type declaration TYPE EmpRecord IS RECORD (ssn LName DName BonusPayment ); NUMBER(6), BOOLEAN, NUMBER(2) employee.ssn%TYPE, employee.LName%TYPE, department.DName%TYPE, BonusCompensation See it in action The BEGIN Clause • About the BEGIN Clause • Performing Data Manipulation • PL/SQL and SQL Features • SQL DML within PL/SQL • Logic Control & Branching • • • • Program Labels & GOTO Loop If-Then-Else Case The BEGIN Clause • Manipulate Internal Program Data • Manipulate Database Data Elements • Using Regular Expressions • Handling Literal Values • Accessing Database Objects • Logic Control and Branching What Can Be Included The BEGIN Clause is where actual processing is performed. • Access Data using SQL • Data Manipulation • Database • Other Data Sources • Standard Logic and Branching Data Available to the Program Database Server Data • Primary Source of Data • Typically retrieved using SELECT…INTO statement Declared Objects • Identified within the DECLARE clause Environment Data • SQL*Plus Environment Variables • Data referenced in Oracle Developer Forms or Reports Performing Data Manipulation Regardless of data origin, one of the main aspects of any program is to manipulate data. There are several techniques we will consider: • Reference basic (scalar) variables and composite types • Handling string literals within the program • Using SQL DML to reference database columns PL/SQL & SQL Manipulation • Working with Character, Numeric, Date and Boolean variables • Handling Special Situations for String Literals • Using Comparison Operators to Evaluate Variables • Using SQL Functions within Program Logic • Using Regular Expressions to Search Character Data CHAR and VARCHAR2 Variables • Assigning a value to a variable requires the assignment operator ‘:=‘. • When manipulating values, you will use the concatenation operator ‘||’ DECLARE EmpLname employee.lname%TYPE; EmpFname employee.fname%TYPE; EmpFullName VARCHAR2(40); BEGIN EmpFname := ‘Jane’; EmpLname := ‘Smith’; EmpFullName := EmpLname || ‘, ‘ || EmpFname; … Handling String Literals • One common problem is the conflict between the use of certain characters as symbols.. DECLARE nValue NUMBER(10) := &enter_value; vMessage VARCHAR(30); BEGIN IF nValue > 60000 THEN vMessage := ‘The value isn’t valid.’; dbms_output.put_line(vMessage); END IF; END; Handling String Literals (cont) • To get around this issue, you must use the string literal q'!...!' DECLARE nValue NUMBER(10) := &enter_value; vMessage VARCHAR(30); BEGIN IF nValue > 60000 THEN vMessage := q'!The value isn't valid.!'; dbms_output.put_line(vMessage); END IF; END; Numeric Variables • Assigning a value to a numeric variable requires the same assignment operator. • Obviously, values must be consistent to the variable type. DECLARE EmpSalary EmpRaisePct employee.Salary%TYPE; NUMBER(2); BEGIN EmpSalary := 50000; EmpRaisePct := 10; EmpSalary := EmpSalary + (EmpSalary * (EmpRaisePct / 100)); … Date Variables • Oracle has built-in features for working with Dates. DECLARE EmpReviewDate EmpNextReview employee.startDate%TYPE; EmpReviewDate%TYPE; BEGIN EmpReviewDate := SYSDATE; EmpNextReview := EmpReviewDate + 100; … Boolean Variables • Boolean variables have many uses. DECLARE EmpSalary HighPaid employee.salary%TYPE; BOOLEAN := FALSE; BEGIN EmpSalary := 50000; HighPaid := (EmpSalary > 40000); IF HighPaid THEN dbms_output.put_line(‘Yes, this salary is high’); END IF; END; Using Comparison Operators • PL/SQL is integrated with Oracle and SQL. DECLARE vString VARCHAR(10) := ‘Doe’; vMessage VARCHAR(30) := ‘String properly evaluated’; BEGIN IF OR OR OR OR OR vString = ‘Doe’ vString != ‘Doe’ vString IS NULL vString LIKE ‘D%’ vString IN (‘Doe’, ‘Smith’, ‘Jones’) vString BETWEEN ‘Daa’ AND ‘Dzz’ THEN dbms_output.put_line(vMessage); END IF; END; Using SQL Functions • Oracle SQL has many built-in functions which may be used to modify column data.. SQL Example SELECT MAX(hours) FROM works_on; PL/SQL Example dbms_output.put_line(‘Best employee name: ‘ || UPPER(BestEmp.LName)); dbms_output.put_line(‘Best employee bonus: ‘ || ROUND(BestEmp.BonusPayment * 1.15, -3)); See it in action SQL DML Within PL/SQL • One of the most frequent tasks will be accessing objects which exist within the database. • This is a major strength of using PL/SQL. • Any valid SQL DML update or transaction control statement may be directly executed in PL/SQL. DML Update Statement Transaction Control Statement INSERT COMMIT UPDATE ROLLBACK DELETE SAVEPOINT LOCK TABLE SET TRANSACTION See it in action Using SELECT • The structures used in PL/SQL depend on the number of records returned by the SELECT statement. • Single-row SELECT statements are nearly identical to all other context (it uses the INTO statement). • Multiple-row SELECT statements require explicit cursors. Single-Row SELECT DECLARE TYPE EmpRecord IS RECORD (ssn Lname Dname BonusPay InactiveEmp employee.ssn%TYPE, employee.Lname%TYPE, department.Dname%TYPE, NUMBER(6)); EmpRecord; BEGIN SELECT essn, Lname, Dname, 0 INTO InactiveEmp FROM employee, department, works_on WHERE employee.dno = department.dnumber AND employee.ssn = works_on.essn AND hours = (SELECT MIN(hours) FROM works_on) AND ROWNUM <= 1; Using INTO • Any valid type may be used in the INTO clause. • The only concern is that the type or types used must match the SELECT exactly See it in action Exceptions & Embedded SQL • When creating a SELECT…INTO statement, you must ensure that it returns a single row. • That is the reason for the ROWNUM <= 1 criteria. • If more than one row were returned, then the TOO_MANY_ROWS exception would have returned. Single-Row SELECT DECLARE TYPE EmpRecord IS RECORD (ssn Lname Dname BonusPay InactiveEmp employee.ssn%TYPE, employee.Lname%TYPE, department.Dname%TYPE, NUMBER(6)); EmpRecord; BEGIN SELECT essn, Lname, Dname, 0 INTO InactiveEmp FROM employee, department, works_on WHERE employee.dno = department.dnumber AND employee.ssn = works_on.essn AND hours = (SELECT MIN(hours) FROM works_on) AND ROWNUM <= 1; No Data Returned • Conversely, if a SELECT…INTO statement does not return any rows, the NO_DATA_FOUND exception is returned. • When using a SELECT…INTO statement, the result must return one and only one row to avoid exceptions. Using Summary Functions • Using summary functions (e.g. SUM(), COUNT(), etc.) eliminates the chances of an exception. • They always return a single row. • Even if no data is found, they return a value of 0 or NULL. SELECT Using Functions DECLARE --Declare variables vHours works_on.hours%TYPE; BEGIN --Select SELECT SUM(HOURS) INTO vHours FROM works_on WHERE essn = &enter_ssn; --Display the result dbms_output.put_line('Total hours: ' || vHours); END; See it in action DML Update Statements • DML Update Statements have no restrictions. • Whether they apply to one row, many rows, or no rows at all, no exceptions are thrown. Using Sequences • Sequences are an automated method of creating a unique value within a table. • Sequences may be referenced within the program just as any other database object. Creating Sequences • Sequences are typically created for one field as the primary key managed by the database. DECLARE BEGIN --Modify the table ALTER TABLE employee ADD EmpID NUMBER(4) CONSTRAINT empPK PRIMARY KEY NOVALIDATE; --Create new sequence CREATE SEQUENCE EmpIDSequence; Referencing a Sequence • Once a Sequence is created, you can reference it within your PL/SQL script. DECLARE BEGIN --Add records to the table referencing the Sequence FOR I IN 1..1000 LOOP INSERT INTO employee (EmpID, lname, fname, dno, salary) VALUES (EmpIDSequence.NEXTVAL, 'Doe', 'Jane', 1, 30000 + I); END LOOP; END; SELECT Sequence • Starting with Oracle 11g and later releases of the database make it possible to reference a sequence as part of a PL/SQL expression. DECLARE newEmpID employee.EmpID%TYPE; BEGIN SELECT EmpIDsequence.NEXTVAL INTO newEmpID FROM dual; INSERT INTO employee (EmpID, lname, fname, dno, salary) VALUES (newEmpID, 'Doe', 'Jane', 1, 45000); END; Faster Sequence Processing • Although the previous method works, it does not scale well. • The same task can now be performed within the PL/SQL script. DECLARE newEmpID employee.EmpID%TYPE; BEGIN newEmpID := EmpIDSequence.NEXTVAL; INSERT INTO employee (EmpID, lname, fname, dno, salary) VALUES (newEmpID, 'Doe', 'Jane', 1, 45000); END; See it in action Logic Control and Branching • As logic within programs become more complex, we need procedural programming structures found in most languages. • • • • Program Labels and GOTO statements LOOP structures IF-THEN-ELSE structures CASE structures Program Labels and GOTO • Labels are location markers. • They can be placed anywhere within a block. • They are enclosed with angle brackets. <<LabelName>> Uses of Labels • Label names can be useful for the following reasons: • For documentation and readability. • A reference point for a GOTO statement. • A reference point for nested programs. See it in action The GOTO Statement • The GOTO statement is simply a jump within program execution. • Rules of GOTO • A valid label name must be specified as the target • Angle brackets are used only to DEFINE the label • The GOTO statement simply identifies the NAME DECLARE BEGIN <<LabelName>> … GOTO LabelName; END; GOTO/Label Eccentricities • Labels cannot be the last statement within a PL/SQL program. • Include the NULL statement to avoid any issues. … IF ActiveEmp.ssn = InactiveEmp.ssn THEN GOTO Conclusion; END IF; … <<Conclusion>> NULL; END; See it in action Loops • Frequently a series of program statements must execute iteratively. PL/SQL allows for this by using Loops. • All Loops have the following basic elements: • • • • A LOOP clause which defines the starting point of the loop. Any number of execution statements follow the loop. The EXIT or EXIT WHEN clause allows you to abort the loop. The CONTINUE or CONTINUE WHEN clause allows you to exit the current iteration of the loop. • An END LOOP statement terminates the loop definition. Fixed Iteration Loop • The first type of Loop is the Fixed Iteration Loop. • An index variable is specified and implicitly declared. • The index increments each time the loop executes. --Prepare a loop FOR I IN 1..1000 LOOP … END LOOP; Using the Index Value • Your logic can leverage the index value. BEGIN --Prepare a loop FOR I IN 1..1000 LOOP --Insert the new record INSERT INTO employee (ssn, lname, fname, salary) VALUES (900000000 + I, 'Doe', 'Jane', 30000 + I); END LOOP; EXCEPTION WHEN OTHERS THEN ROLLBACK; END; Loop in Reverse • A variation on the FOR…NEXT loop is to execute in reverse order. • The following example will start with number 10 and proceed to 1. --Prepare a loop FOR I IN REVERSE 1..10 LOOP --Insert the new record INSERT INTO employee (ssn, lname, fname, salary) VALUES (900000000 + I, 'Doe', 'Jane', 30000 + I); END LOOP; See it in action Indefinite Loops • Indefinite loops execute indefinitely until either an exception occurs or the EXIT statement is issued. • The beginning and ending statements are LOOP…END LOOP. See it in action Conditional Loops • Conditional loops execute indefinitely while a given condition is TRUE. • Generally this loop is used when the loop logic changes the conditional expression. See it in action Nested Loops • For highly complex logic problems it may be necessary to have several levels of nested loops. • Nested loops are ideal when working with hierarchies. See it in action IF-THEN-ELSE • IF-THEN-ELSE structures are typical of most programming languages. • They are used to evaluate conditions where the number of cases is limited. DECLARE birth_month message CHAR(3) := &enter_birth_month; VARCHAR(25); BEGIN --Test the month IF birth_month = 'JAN' THEN message := 'Start of the year'; ELSE message := 'No comment'; END IF; ELSIF • The ELSIF (ELSE IF) clause allows you to test for more than one condition in a single IF statement. DECLARE birth_month message CHAR(3) := &enter_birth_month; VARCHAR(25); BEGIN --Test the month IF birth_month = 'JAN' THEN message := 'Start of the year'; ELSIF birth_month = 'FEB' THEN message := 'Short month'; ELSE message := 'No comment'; END IF; … Nested IF-THEN-ELSE • PL/SQL allows for nested IF statements … --Test the month IF birth_month = 'JAN' THEN message := 'Start of the year'; ELSIF birth_month = 'FEB' THEN message := 'Short month'; IF TO_CHAR(x_bdate, 'DD') = 1 THEN message := 'The first day of the ' || message; END IF; ELSE message := 'No comment'; END IF; … See it in action CASE • As an alternative to IF-THEN-ELSE statement for complex logic structures, PL/SQL offers a CASE statement. • It’s perfect when many conditions are required. • The CASE statement has multiple forms: • Selector – This is when a single expression is evaluated • Searched – This is where a series of complex conditions are searched. The first TRUE condition dictates the output. CASE Selector • Notice that there is a single variable being tested. … birth_month := enter_birth_month; … --Test the month CASE birth_month WHEN 'JAN' THEN WHEN 'FEB' THEN WHEN 'MAR' THEN WHEN 'APR' THEN WHEN 'MAY' THEN WHEN 'JUN' THEN WHEN 'JUL' THEN ELSE message := END CASE; … message := 'Start of the year'; message := 'Short month'; message := 'Spring has sprung'; message := 'Watch for showers'; message := 'Smell the flowers'; message := 'Time for brides'; message := 'Vacation time'; 'No comment'; CASE Searched • A more realistic scenario, is where you wish to evaluate more than one condition. … --Test multiple conditions CASE WHEN vAge < 20 THEN message := ‘Young employee'; WHEN x_salary < 30000 THEN message := ‘Inexpensive employee'; WHEN vAge BETWEEN 40 AND 50 AND x_salary BETWEEN 30000 AND 40000 THEN message := ‘Middle age, Middle salary'; ELSE message := 'No analysis made'; END CASE; … Additional Features of CASE • The following features govern the execution of a CASE statement: • Once a condition has been selected, the remaining conditions are not evaluated. • If none of the conditions are met, the ELSE clause is executed. • If none of the conditions are met and an ELSE clause is not specified, the CASE_NOT_FOUND exception is raised. See it in action The EXCEPTION Clause • Review the Different Exception Types • Trapping Exceptions • Identifying Exception Details • User-Declared Exceptions • Exception Functions • Implicit Cursor Attributes Types of Exceptions Exceptions which might occur during processing may be classified according to the following categories: Error Type Description Program Processing Errors which occur during the execution of the program Internal Oracle Errors which arise from the Oracle environment User Declared Errors anticipated which you wish to trap and intentionally transfer execution from the BEGIN clause to the EXCEPTION clause Exception Processing There are several important points pertaining to processing exceptions. • Virtually anything that can be done in the BEGIN clause can be done in the EXCEPTION clause. • Once control has been passed to the EXCEPTION clause, control cannot be passed back to the BEGIN clause. • When an exception is detected, control is passed to the EXCEPTION clause. If the EXCEPTION clause does not exist or the error is not handled, the program aborts with an error condition. Trapping Exceptions Exception handlers are declared using the WHEN statement. There are a few different options for routine exceptions into their respective exception logic. There are several techniques we will consider: Exception Description Single This is a program which should execute only when the particular exception is fired. Set Using PL/SQL conditional logic you can handle several exceptions with the same logic. Global Handler This is where you use the WHEN OTHERS test. Trapping Exceptions (cont) EXCEPTION --Test for a single condition WHEN zero_divide THEN … --Test for a set of exception conditions WHEN no_data_found OR too_many_rows THEN … --Test for all others WHEN OTHERS THEN … See it in action Identify Exception Detail It’s essential to understand the different exceptions and their root causes. This will only make you a better PL/SQL programmer. • The following is a partial list of the most common exceptions names you are likely to use. EXCEPTION Name Operation NO_DATA_FOUND TOO_MANY_ROWS SELECT....INTO CURSOR_ALREADY_OPEN INVALID_CURSOR Explicit Cursors Identify Exception Detail EXCEPTION Name Operation CASE_NOT_FOUND Missing match or ELSE clause in CASE structure INVALID_NUMBER VALUE_ERROR ZERO_DIVIDE Value errors when assigning values to variables LOGIN_DENIED NOT_LOGGED_ON Database connect errors PROGRAM_ERROR STORAGE_ERROR TIMEOUT_ON_RESOURCE Internal fatal errors Isolating the Specific Exception Additionally, the following features help you isolate and handle exceptions. • When errors don’t have a name, you can define your own using the EXCEPTION_INIT feature. • If the error has no system or user-defined name, the built-in functions SQLCODE and SQLERRM will reveal the nature of the exception • When SQL DML statements have been executed, implicit cursor attributes provide information. • User-Defined events can also be declared. See it in action User-Defined Exceptions Many database errors may occur that are not within the pre-defined table outlined earlier. These must be handled with the global WHEN OTHERS test. Instead of using the global error handler, we can issue a compiler directive (PRAGMA) for any Oracle database error (EXCEPTION_INIT). There are many sites that explain the different Oracle Error Messages and Codes See it in action Why Use Error Functions? Hundreds of different errors can arise within a PL/SQL program, yet we have only seen a handful of defined error names. We can create our own exception names using PRAGMA EXCEPTION_INIT, but that can get tedious. PL/SQL has a standard component associated to the global error handler that can give you more information about an exception. SQLCODE and SQLERRM If your EXCEPTION block uses the WHEN OTHERS handler, you can use the following objects to ascertain the problem: • SQLCODE – Returns the exception code • SQLERRM – Returns the error message By evaluating these objects, you can make your PL/SQL program smarter. SQLCODE and SQLERRM DECLARE BEGIN UPDATE employee SET lname = NULL; EXCEPTION WHEN OTHERS THEN dbms_output.put_line('Error code: ' || SQLCODE); dbms_output.put_line('Error message: ' || SQLERRM); END; Error code: -1407 Error message: ORA-01407: cannot update ("STUDENT1"."EMPLOYEE". "LNAME") to NULL PL/SQL Procedure successfully completed See it in action PRAGMA EXCEPTION_INIT Creating a new EXCEPTION is a 2-step process: 1. Declare a user-assigned name as EXCEPTION 2. Associate the name with an Oracle error number using the PRAGMA EXCEPTION_INIT command DECLARE --User-assigned exception name declaration not_null_constraint EXCEPTION; --Equate the new exception name to the corresponding --Oracle error number. --IMPORTANT – Make sure the number is correct PRAGMA EXCEPTION_INIT (not_null_constraint, -1407); What is an Implicit Cursor? Each time a SQL DML statement is executed within PL/SQL, Oracle automatically creates an internal work area known as a SQL cursor. SQL cursor object details • We can access attributes within this cursor to determine the action results. • The cursor and attributes are available regardless of a successful or failed DML operation. Implicit Cursor Attributes The following list outlines the different SQL Cursor Attributes: Attribute SQL%FOUND Type T/F Explanation Determines whether the DML statement affected any rows. SQL%NOTFOUND T/F Logical opposite of the SQL%FOUND attribute More meaningful whenthe number of rows affected by the DML SQL%ROWCOUNT Int Equals using explicit cursors statement SQL%ISOPEN T/F Indicates whether or not the cursor is currently open. SQL%ROWCOUNT & SELECT..INTO For single-row SELECT…INTO statements, the attribute values differ somewhat from DML update statements. • Equal to 0 – When no rows were fetched and the NO_DATA_FOUND exception was raised. • Equal to 1 – When the statement returned one and only one row. No exceptions generated. • Equal to 1 – When the statement returned too many rows and the TOO_MANY_ROWS exception was raised. See it in action User-Defined Events User-Defined events are not internal errors. However, they are an effective way to create business rules for your programs. Steps to create an events as an exception: • Within DECLARE, assign a name to EXCEPTION • Within BEGIN, create a condition to RAISE the EXCEPTION • Within EXCEPTION, handle the exception as desired See it in action Explicit Cursors • Understand the Concept and Purpose of Explicit Cursors • Identify the Advantages of Explicit Cursors • Explore Explicit Cursor Attributes • Perform Updates using Explicit Cursors • Review Extended Explicit Cursor Techniques and Features About Explicit Cursors • Explicit cursors are named pointers to rows and columns within the database. • They are used whenever sequential processing is required. Cursor Result Current Cursor Pointer SSN LName Salary DName MgrSSN 888665555 Borg 55000 Headquarters 888665555 333445555 Wong 44000 Research 333445555 987654321 Wallace 43000 Administration 987654321 66884444 Naraan 41800 Research 333445555 123456789 Smith 33000 Research 333445555 999887777 Zelaya 25000 Administration 987654321 A Cursor Example - DECLARE • CURSOR declarations must be created within the DECLARE clause. • Any valid SQL statement is permitted. • A variable containing the structure holding the data must also be created. DECLARE --Declare the cursor CURSOR Employees IS SELECT * FROM employee; --Declare the row type associated to the CURSOR EmpRecord employee%ROWTYPE; A Cursor Example - BEGIN • All CURSOR processing is performed within the BEGIN clause. • The CURSOR must be opened • The FETCH statement advances the CURSOR pointer to the next record • After each FETCH statement, the %FOUND and %NOTFOUND attributes must be tested. • If the FETCH statement results in a new row, execute any desired processing • When completed, the CURSOR must be closed A Cursor Example - BEGIN … BEGIN OPEN Employees; LOOP FETCH Employees INTO EmpRecords; EXIT WHEN Employees%NOTFOUND; --Display the record detail dbms_output.put_line('Employees ' || EmpRecords.LName || ' earns ' || EmpRecords.Salary); END LOOP; CLOSE Employees; END; Advantages of Explicit Cursors There are several important advantages to using Explicit CURSORS. • You can programmatically cycle through multiple records. • The common EXCEPTION which can occur with the SELECT…INTO statement never happen • TOO_MANY_ROWS because of the FETCH command • NO_DATA_FOUND because the pointer simply stays on the last record See it in action Cursor Attributes Explicit cursors have the same attributes as implicit cursors. • Names always use the following naming format: CursorName%AttributeName Cursor Attribute Values The values returned by the attributes are slightly different from Implicit cursors • %FOUND and %NOTFOUND indicate whether or not the FETCH statement received data. • %ROWCOUNT indicates which row the FETCH statement received. • %ISOPEN is True/False depending on whether the cursor is open and data is available. Cursor Attributes Illustrated EMPS_AND_DEPTS Cursor Pointer SSN LName Salary DName MgrSSN 888665555 Borg 55000 Headquarters 888665555 333445555 Wong 44000 Research 333445555 987654321 Wallace 43000 Administration 987654321 66884444 Naraan 41800 Research 333445555 123456789 Smith 33000 Research 333445555 999887777 Zelaya 25000 Administration 987654321 987987987 Jabour 25000 Administration 987654321 emps_and_depts%FOUND = True emps_and_depts%NOTFOUND = False emps_and_depts%ROWCOUNT = 5 emps_and_depts%ISOPEN = True See it in action Using the CONTINUE Statement Unlike EXIT which terminates the execution of a loop in its entirety, CONTINUE terminates the current iteration of the loop. • Like EXIT, the CONTINUE statement includes a WHEN clause. See it in action Extended Cursor Techniques Beyond the basic cursor technique discussed so far, there are additional techniques which are important for you to understand. These techniques are: • Declaring and using Updateable Cursors • Incorporating Parameters into Cursor Declarations • Using the abbreviated FOR…LOOP cursor syntax Updatable Cursors As part of the row-by-row processing, updates may need to be performed. This is done by incorporating the FOR UPDATE OF clause. DECLARE --Declare the cursor CURSOR Employees IS SELECT * FROM employee FOR UPDATE OF salary, LName; Critical Notes for Update Cursor Once an UPDATE cursor is opened, the underlying data is locked. These rows will remain locked until: • The cursor is closed • The transaction is terminated with either COMMIT or ROLLBACK WHERE CURRENT OF Clause When working with Updatable cursors, you will need to use a SQL DML update command to physically perform the update. You must include the phrase WHERE CURRENT OF CursorName BEGIN … --Update the record UPDATE Employees SET salary = salary – PayCut, Lname = UPPER(Lname) WHERE CURRENT OF Employees; … See it in action Cursor Parameters The search criteria stated within the cursor declaration may be altered each time the cursor is opened by the means of a parameter. Parameter Rules: • Parameters are defined within the cursor declaration. • Parameters are used in the WHERE clause. • The Parameter value is passed when the cursor is opened. Parameter Declaration Parameters are defined within the cursor declaration using the following syntax: ObjectName Type DECLARE --Declare the cursor CURSOR Employees (SelectDept department.dnumber%TYPE) IS SELECT * FROM employee WHERE dno = SelectDept FOR UPDATE OF salary; … Setting the Parameter Somewhere within the program logic you need to compute a value for the parameter. --Retrieve the value for the parameter SELECT d.number INTO SelectDepartment FROM department d INNER JOIN dept_locations dl on d.dnumber = dl.dnumber WHERE dl.dlocation = 'Stafford' AND ROWNUM <= 1; --Open the cursor OPEN Employees (SelectDepartment); See it in action FOR…LOOP Cursors The FOR…LOOP Cursor is a very effective technique that greatly improves performance. • Simplifies the code • More concise • Manages Cursor Opening and Closing • Manages EXIT • FETCH is automatic Standard Cursor Syntax DECLARE CURSOR Employees IS SELECT * FROM employee; EmpRecord Employees%ROWTYPE; BEGIN OPEN Employees; LOOP FETCH Employees INTO EmpRecord; EXIT WHEN Employees%NOTFOUND; dbms_output.put_line(‘Employee: ‘ || Employees.Lname); END LOOP; CLOSE Employees; END; FOR…LOOP Cursor Syntax BEGIN --Create FOR…LOOP cursor FOR Employees IN Each time the FOR is executed, the (SELECT * record is placed in an implicitly FROM employee) LOOP END END; declared object SELECT statement dbms_output.put_line('Employee: ' || type Employees.Lname); declares the Cursor Implicit FETCH is performed LOOP; along with a check of the If %NOTFOUND is True, the %NOTFOUND attribute implicit EXIT is fired along with an implicit CLOSE This shortcut syntax is possible because the system understands that cursor processing follows a set pattern. See it in action Nested Blocks • What are Nested Blocks? • Why Use Nested Blocks? • Rules for Nested Blocks • Global vs. Local Objects • Global vs. Local Exceptions What are Nested Blocks? As the size and complexity of your programs increase, a more advanced way of organizing the code becomes essential. • A Nested Block is a complete PL/SQL program block enclosed within the BEGIN section of another block. BEGIN Outer Block BEGIN … END; END; Inner Block Why Use Nested Blocks? • Nested Blocks are helpful in enclosing SELECT or other statements that may generate an exception. • If an Exception occurs, it is handled by the Inner Block. • Processing may continue in the Outer Block • If a Nested Block were not used in this example, the entire program would exit by passing control to the EXCEPTION Clause. Rules for Nested Blocks • There are specific rules associated to Nested Blocks: • The boundaries of inner and outer blocks are identified using labels and the END statement. • A maximum of 200 Nested Blocks may be created. • Nested Blocks may NOT begin within the DECLARE clause of the enclosing block. • A Nested Block may only begin within the BEGIN or EXCEPTION clause of the enclosing block. See it in action Global vs. Local Objects When using Nested Blocks, the declared objects within the different blocks become either global or local. Object Description Global Any object declared in the Outer Block are global Local Any declaration made within the Inner Block are local and only visible to the Inner Block. Object names may be reused as local objects within inner blocks. BlockName.ObjectName Global vs. Local Exceptions There is also the concept of both Global and Local Exceptions. • All exceptions are considered Local. • The system looks for the EXCEPTION clause within that block. • If no EXCEPTION clause is found, the system branches to the Outer Block. • If no EXCEPTION clause if found in the outermost block, the program terminates. Global vs. Local Exceptions When an EXCEPTION is handled in an Inner Block, you may consider it partially handled. • You can use the RAISE statement to branch the exception in the manner you wish. See it in action Declared Subprograms • What are Subprograms? • Distinction with Nested Blocks • Distinction with Stored Program Units • Syntax Requirements What are Subprograms? The concept of a the Subprogram is common with any programming environment. • It’s the method of making your programs modular. • Subprograms may be either a Procedure or Function. Type Description Procedure Performs an action Function May perform an action, but its primary purpose is to return a value Distinction with Nested Blocks • Subprograms are similar to Nested Blocks, but the differences are important to understand. Similarities • Subprograms are defined within an existing PL/SQL program. Differences • Subprograms are defined in the DECLARE clause whereas Nested Blocks are defined in the BEGIN or EXCEPTION clause. • Subprograms execute when they are called within the execution portion of the outer program. Distinction with Stored Program Units • Subprograms are more similar to Stored Program Units than Nested Blocks, but there is one important difference. Similarities • Subprogram syntax, declaration rules, and other details are practically identical. Differences • Stored Program Units are independent programs physically stored on the database server. • Since the Stored Program Unit is stored on the database server, performance is greatly improved. Subprogram Syntax The following rules must be followed when creating Subprograms: • When declaring a Subprogram, you use the following format PROCEDURE name (parameter type) • Parameter types must be unconstrained (no size). • There is no explicit DECLARE clause. Declarations are made immediately following the IS clause. • The END statement must reference the Subprogram name. See it in action