This document provides an overview of Oracle SQL and PL/SQL. It introduces databases and the main components of Oracle, including SQL*Plus, PL/SQL, and SQL Developer. Various SQL commands are demonstrated for retrieving, filtering, ordering and aggregating data from tables. Conditional expressions, operators and functions are covered, along with the GROUP BY, HAVING and ROLLUP clauses.
Download as PPT, PDF, TXT or read online on Scribd
0 ratings0% found this document useful (0 votes)
149 views
Oracle11g Slides
This document provides an overview of Oracle SQL and PL/SQL. It introduces databases and the main components of Oracle, including SQL*Plus, PL/SQL, and SQL Developer. Various SQL commands are demonstrated for retrieving, filtering, ordering and aggregating data from tables. Conditional expressions, operators and functions are covered, along with the GROUP BY, HAVING and ROLLUP clauses.
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 319
1
Oracle SQL, PL/SQL
By Bhavna Philipose Training Consultant : MCP 104.01.05 2 Module Getting Started with Oracle Overview Introduction to Databases Introducing SQL Main Components of Oracle Starting SQL * Plus Exiting SQL * Plus 3 Introduction to Databases
Computerized record-keeping system. EMPNO ENAME JOB MANAGER HIREDATE SALARY COMMISSI ON DEPTNO 7369 SMITH CLERK 7902 17-DEC- 1980 800 20 7499 ALLEN SALESMAN 7698 20-FEB-1981 1600 300 30 7521 WARD SALESMAN 7698 22-FEB-1981 1250 500 30 7566 JONES MANAGER 7839 02-APR-1981 2975 20 7654 MARTIN SALESMAN 7698 28-SEP-1981 1250 1400 30 7698 BLAKE MANAGER 7839 01-MAY- 1981 2850 30 7782 CLARK MANAGER 7839 09-JUN-1981 2450 0 10 7788 SCOTT ANALYST 7566 19-APR-1987 3000 20 EMPLOYEE 4 Introducing SQL 5 Main Components of Oracle SQL * Plus
6 Main Components of Oracle iSQL * Plus
7 Main Components of Oracle PL/SQL
8 Starting SQL*Plus 9 Starting SQL * Plus from Command Prompt 10 Exiting SQL*Plus SQL> EXIT
11 SQL Developer
Oracle SQL Developer is a free graphical tool for database development and querying the Database. Using SQL Developer, you can browse database objects, run SQL statements and SQL scripts, and edit and debug PL/SQL statements. SQL Developer can connect to any Oracle Database version 9.2.0.1 and later and runs on Windows, Linux and Mac OSX. It enhances productivity and simplifies your database development tasks.
12 Connection To a Oracle Database 13 Browsing Objects 14 PL/SQL Creating Functions 15 Module : Editing SQL Commands
Overview Entering SQL commands Editing SQL commands Managing SQL files 16 Entering and Editing SQL Commands Terminating SQL statement: a semicolon at the end of a line, a semicolon on a line by itself, a slash ("/") on a line by itself.
Viewing contents of SQL buffer: SQL> prompt: SQL> list;
Viewing specific line: SQL> 2 17 Entering and Editing SQL Commands SQL> FROM meployee SQL> change/mep/emp SQL> c/mep/emp SQL> c/emp SQL> delSQL> input FROM employee SQL> append , emp_name SQL> save training.sql
18 Managing SQL files SQL> get training.sql SQL> @ training.sql SQL> run training.sql SQL> clear buffer SQL> spool C:\training SQL> spool off SQL> spool out
19 Module : Data Retrieval & Ordering Output Overview Simple Data Retrieval Describing Table Structure Conditional Retrieval using Arithmetic, Relational, Logical and Special Operators The ORDER BY clause. Aggregate functions The GROUP BY and HAVING clause 20 Data Retrieval SQL> SELECT * FROM tab;
SQL> DESC dept Name Null? Type ----------------------------------------------------------------------- -------- ---------------- DEPTNO NUMBER(2) DNAME VARCHAR2(14) LOC VARCHAR2(13) BUDGET NUMBER
21 Data Retrieval SQL> SELECT * FROM employee;
SQL> SELECT emp_code, emp_name FROM employee;
SQL> SELECT distinct dept_code FROM employee;
22 Conditional Retrieval SQL> SELECT * FROM employee WHERE salary > 3500;
SQL> SELECT emp_code, emp_name FROM employee WHERE dept_code = 'MKTG';
23 Relational Operators = equal to != not equal to ^= not equal to <> not equal to > greater than < less than >= greater than or equal to <= less than or equal to
SQL> SELECT * FROM employee WHERE salary > 3000; SQL> SELECT emp_name FROM employee WHERE dept_code != 'MKTG'; SQL> SELECT * FROM employee WHERE emp_name = 'Vijay Gupta'; 24 Logical Operators The AND Operator SQL> SELECT * FROM employee WHERE dept_code = 'MKTG' AND sex = 'F';
SQL> SELECT * FROM employee WHERE salary >= 3000 AND salary <= 4000;
The OR Operator SQL> SELECT * FROM employee WHERE dept_code = 'MKTG' OR dept_code = 'FIN';
The NOT Operator SQL> SELECT * FROM employee WHERE NOT dept_code = 'MKTG'; 25 Special Operators The BETWEEN operator SQL> SELECT * FROM employee WHERE salary BETWEEN 3000 and 4000;
SQL> SELECT * FROM employee WHERE date_join BETWEEN '01-JAN-80' and '31-DEC-89'
The IN operator SQL> SELECT * FROM employee WHERE dept_code IN ('MKTG', 'FIN');
SQL> SELECT * FROM employee WHERE dept_code NOT IN ('MKTG', 'FIN'); 26 Special Operators The LIKE operator
SQL> SELECT * FROM employee WHERE emp_name LIKE 'P%'; SQL> SELECT * FROM employee WHERE emp_name LIKE '%Gupta'; SQL> SELECT * FROM employee WHERE emp_name LIKE '%Gupta%'; SQL> SELECT * FROM employee WHERE grade LIKE '_1';
The IS NULL operator
SQL> SELECT * FROM employee WHERE reports_to IS NULL; SQL> SELECT * FROM employee WHERE reports_to IS NOT NULL;
SQL> SELECT * FROM product WHERE direct_sales + indirect_sales > target;
SQL> SELECT prod_code, prod_name, direct_sales + indirect_sales FROM product;
SQL> SELECT prod_code, direct_sales + indirect_sales "Total sales" FROM product; 28 Ordering the SELECT Query Output Ordering on single column SQL> SELECT * FROM employee ORDER BY emp_code;
SQL> SELECT * FROM employee WHERE sex = 'M' ORDER BY emp_name;
SQL> SELECT * FROM employee ORDER BY age DESC;
Ordering on multiple columns
SQL> SELECT * FROM employee ORDER BY dept_code, emp_name;
SQL> SELECT * FROM employee ORDER BY dept_code, age DESC; 29 Substitution Variables ... salary = ? department_id = ?
... last_name = ? ... I want to query different values. 30 Substitution Variables substitution variables Substitution Variables Use substitution variables to supplement the following: WHERE conditions ORDER BY clauses Column expressions Table names Entire SELECT statements
Substitutio n Variables
Use substitution variables to: Temporarily store values with single- ampersand (&) and double-ampersand (&&) substitution
31 SELECT product_id, warehouse_id, quantity_on_hand FROM inventories WHERE product_id = &product_id ; Using the Single-Ampersand Substitution Variable Use a variable prefixed with an ampersand (&) to prompt the user for a value: 32 2-32 Using the Single-Ampersand Substitution Variable 33 SELECT last_name, department_id, salary*12 FROM employees WHERE job_id = '&job_title' ; Character and Date Values with Substitution Variables Use single quotation marks for date and character values: 34 2-34 Specifying Column Names, Expressions, and Text SELECT &column_name FROM inventories WHERE &Condition ORDER BY &Order_column ; 35 SELECT employee_id, last_name, job_id, &&column_name FROM employees ORDER BY &column_name ;
Using the Double-Ampersand Substitution Variable Use double ampersand (&&) if you want to reuse the variable value without prompting the user each time: 36 2-36 Using the DEFINE Command
Use the UNDEFINE command to remove a variable. DEFINE order_num = 2458
SELECT order_id, order_date, order_mode, order_total FROM orders WHERE order_id = &order_num ;
UNDEFINE order_num Use the DEFINE command to create and assign a value to a variable.
37 SET VERIFY ON SELECT employee_id, last_name, salary FROM employees WHERE employee_id = &employee_num; Using the VERIFY Command Use the VERIFY command to toggle the display of the substitution variable, both before and after SQL Developer replaces substitution variables with values: 38 Aggregate Functions SQL> SELECT COUNT (*) FROM employee; SQL> SELECT SUM (salary) FROM employee; SQL> SELECT AVG (age) FROM employee; SQL> SELECT MAX (salary) FROM employee; SQL> SELECT MIN (salary) FROM employee; SQL> SELECT * FROM employee WHERE salary = (SELECT MIN (salary) FROM employee);
39 The GROUP BY clause SQL> SELECT dept_code, sum (salary) FROM employee GROUP BY dept_code;
40 The HAVING Clause SQL> SELECT dept_code, sum (salary) FROM employee GROUP BY dept_code HAVING sum (salary) > 10000;
SQL> SELECT dept_code, sum (salary) FROM employee WHERE age > 30 GROUP BY dept_code HAVING sum (salary) > 10000 ORDER BY sum (salary) desc; 41 SQL for Aggregation ROLLUP calculates aggregations such as SUM, COUNT, MAX, MIN, and AVG at increasing levels of aggregation, from the most detailed up to a grand total.
To find the product-wise and productgroup-wise total across regions: select prodgr_name , prod_name ,region,sum (target) from prodgrup, product where prodgrup.prodgr_code = product.prodgr_code group by ROLLUP( prodgr_name, prod_name,region) 42 SQL for Aggregation GROUPING Function Two challenges arise with the use of ROLLUP and CUBE. First, how can you programmatically determine which result set rows are subtotals, and how do you find the exact level of aggregation for a given subtotal Second, what happens if query results contain both stored NULL values and "NULL" values created by a ROLLUP or CUBE? How can you differentiate between the two
GROUPING handles these problems. If the NULL indicates the row is a subtotal, GROUPING returns 1. Any other type of value, including a stored NULL, returns 0. 43 SQL for Aggregation For eg. select prodgr_name, prod_name, region, sum (target), grouping(prod_name) gr_prd_name, grouping(region) gr_region from prodgrup, product where prodgrup.prodgr_code = product.prodgr_code group by ROLLUP( prodgr_name, prod_name,region);
44 SQL for Aggregation Thus Grouping function can be used as follows: select case when GROUPING(prodgr_name)= 1 and grouping(prod_name) = 1 and GROUPING(region) = 1 then 'GRAND TOTAL' else prodgr_name end "group", case when GROUPING(prodgr_name)= 0 and grouping(prod_name) = 1 then 'GROUP TOTAL' else prod_name end prod_name, case when GROUPING(prodgr_name)= 0 and grouping(prod_name) = 0 and GROUPING(region) = 1 then 'PRODUCT TOTAL' else region end region, sum (target) from prodgrup, product where prodgrup.prodgr_code = product.prodgr_code group by rollup(prodgr_name,prod_name,region); This replaces all the null values caused by rollup/cube with some meaningful values.
45 SQL for Aggregation CUBE is an extension similar to ROLLUP, enabling a single statement to calculate all possible combinations of aggregations select prodgr_name, prod_name, region, sum (target), grouping(prod_name) gr_prd_name, grouping(region) gr_region from prodgrup, product where prodgrup.prodgr_code = product.prodgr_code group by cube( prodgr_name, prod_name,region);
The CUBE, ROLLUP extension lets you specify just the groupings needed in the GROUP BY clause. This allows efficient analysis across multiple dimensions.
46 SQL for Aggregation Computing a CUBE creates a heavy processing load, so replacing cubes with grouping sets can significantly increase performance.
CUBE(a, b, c) This statement is equivalent to: GROUPING SETS ((a, b, c), (a, b), (a, c), (b, c), (a), (b), (c), ())
ROLLUP(a, b, c) This statement is equivalent to: GROUPING SETS ((a, b, c), (a, b), ()) 47 Module Built-In Functions Overview Numeric functions Character functions Date functions Special formats with Date data types Conversion functions 48 Functions on Numeric data types Function Returns Example Result ceil (n) Nearest whole integer greater than or equal to n. SELECT ceil (9.86) FROM dual; 10 floor (n) Largest integer equal to or less than n. SELECT floor (9.86) FROM dual; 9 mod (m, n) Remainder of m divided by n. If n = 0, then m is returned. SELECT mod (11, 4) FROM dual; 3 power (m, n) Number m raised to the power of n. SELECT power (5, 2) FROM dual; 25 round (n, m) Number n rounded off to m decimal places. SELECT round (9.86, 1) FROM dual; 9.9 sign (n) If n = 0, returns 0. If n > 0, returns 1. If n < 0, returns -1. SELECT sign (9.86) FROM dual; 1 sqrt (n) Square root of n. SELECT sqrt (25) FROM dual; 5 49 Functions on Character data type Function Returns Example Result initcap (x) Changes the first character of each word to capital letters. SELECT initcap ( 'inder kumar gujral' ) FROM dual; Inder Kumar Gujral lower (x) Converts the entire string to lowercase. SELECT lower ( 'Inder Kumar Gujral' ) FROM dual; inder kumar gujral upper (x) Converts the entire string to uppercase. SELECT upper ( 'Inder Kumar Gujral' ) FROM dual; INDER KUMAR GUJRAL replace (char, str1, str2) Every occurrence of str1 in char is replaced with str2. SELECT replace( 'Cap' , 'C', 'M' ) FROM dual; Map soundex (x) Every word that has a similar phonetic sound, even if it is spelled differently. SELECT emp_name FROM employee WHERE soundex (emp_name) = soundex ('Sivananda') Shivanand Joshi substr (char, m, n) Part of char, starting FROM position m and taking characters. SELECT substr ('Computer', 1, 4) FROM dual; Comp length (char) Length of char. SELECT length ('Oracle') FROM dual; 6 50 Functions on Date data types Function Returns Example Result sysdate Current date and time. SELECT sysdate FROM dual; 25-NOV-97 last_day (date) Last day of the month for the given date. SELECT last_day (sysdate) FROM dual; 30-NOV-97 add_months (date, n) Adds n months to the given date. SELECT add_months (sysdate, 2) FROM dual; 25-JAN-98 months_between (date1, date2) Difference in months between date1 and date2. SELECT months_between (sysdate, '01-JAN-99') FROM dual; -13.20232 next_day (date, day) Date is the specified day of the week after the given date. SELECT next_day (sysdate, 'sunday') FROM dual; 30-NOV-97 51 Formats with Date data types Format Returns Example Result Y Last digit of the year. SELECT to_char (sysdate, 'Y') FROM dual; 7 YY Last 2 digits of the year. SELECT to_char (sysdate, 'YY') FROM dual; 97 YYY Last 3 digits of the year SELECT to_char (sysdate, 'YYY') FROM dual; 997 YYYY All 4 digits of the year SELECT to_char (sysdate, 'YYYY') FROM dual; 1997 year Year spelled out. SELECT to_char (sysdate, 'year') FROM dual; Nineteen ninety- seven Q Quarter of the year (Jan through Feb is 1). SELECT to_char (sysdate, 'q') FROM dual; 4 52 Formats with Date data types MM Month of the year (01-12). SELECT to_char (sysdate, 'mm') FROM dual; 11 RM Roman numeral for month. SELECT to_char (sysdate, 'rm') FROM dual; XI month Name of the month as a nine-character long string. SELECT to_char (sysdate, 'month') FROM dual; novemb er WW Week of the year SELECT to_char (sysdate, 'ww') FROM dual; 48 W Week of the month SELECT to_char (sysdate, 'w') FROM dual; 4 53 Format with Date data types Format Returns Example Result DDD Day of the year; January 01 is 001; December 31 is 365 or 366. SELECT to_char (sysdate, 'ddd') FROM dual; 329 DD Day of the month. SELECT to_char (sysdate, 'dd') FROM dual; 25 D Day of the week. Sunday = 1; Saturday = 7. SELECT to_char (sysdate, 'd') FROM dual; 3 DY Abbreviated name of the day. SELECT to_char (sysdate, 'dy') FROM dual; tue HH or HH12 Hour of the day (01-12). SELECT to_char (sysdate, 'hh') FROM dual; 04 HH24 Hour of the day in 24-hour clock. SELECT to_char (sysdate, 'hh24') FROM dual; 16 MI Minutes (00-59) SELECT to_char (sysdate, 'mi') FROM dual; 20 SS Seconds (00-59) SELECT to_char (sysdate, 'ss') FROM dual; 22 54 Module : Advanced Queries
Overview
Table joins
Sub queries
Set operators
Multi-table insert and delete
MERGE statement
55 JOINS Equi Join
SQL> SELECT emp_name, dept_name FROM EMPLOYEE, DEPT WHERE dept.dept_code = employee.dept_code;
56 JOINS Self Join
SQL> SELECT a.emp_name, b.emp_name FROM employee A, employee B WHERE A.reports_to = B.emp_code;
57 JOINS Outer Join
SQL> SELECT A.emp_name, B.emp_name FROM employee A, employee B WHERE A.reports_to = B.emp_code (+);
65 Data Types Data Type Description Example char (n) Fixed-length character data. Max 2000 bytes dept_code char (4) varchar (n) Variable-length character data. Max 4000 bytes dept_code varchar2 (4) varchar2 (n) Variable-length character data. Max size is 4000 bytes dept_code varchar (4) number (p, s) Numeric data, 'p' is the total length and s is the number of decimal places. reading number (5, 2). Maximum value: 99.99 Date Date and time. Range is 01/01/4712 BC to 31/12/4712 AD. date_join date 66 Data Types Data Type Description Example long Variable-length character data. Max 2 GB remarks long raw (n) Binary format data. Max size 2000 bytes esc_seqraw (15) Long raw Same as raw, but maximum size is 2 GB. picture long raw BLOB Stores binary large objects up to 4GB CLOB Stores character large objects up to 4GB. BFILE Enables access to binary file LOBs that are stored in the file system outside the Oracle database. Maximum file size up to 4GB. 67 Module : Inserting, Modifying & Deleting Data Overview Inserting Data into a Table Inserting Data into a Table using Sub query Modifying Data in a Table Deleting Data from a Table
68 Inserting Data into a Table SQL> desc dept; Name Null? Type ------------- --------------------- ------------------ DEPT_CODE NOT NULL VARCHAR2(4) DEPT_NAME NOT NULL VARCHAR2(20)
SQL> INSERT INTO dept VALUES ('MKTG', 'Marketing'); SQL> INSERT INTO dept VALUES ('FIN', 'Finance'); SQL> INSERT INTO dept VALUES ('TRNG', 'Training');
INSERT INTO table-name VALUES (value1, value2, ...); 69 Inserting Data into Table SQL> INSERT INTO employee (emp_code, age, emp_name) VALUES(101, 33, 'Sunil');
SQL> INSERT INTO senior SELECT * FROM employee WHERE age > 50;
70 Modifying and Deleting Data SQL> UPDATE employee SET salary = salary + 100; SQL> UPDATE employee SET salary = salary + 200 WHERE sex = 'F';
SQL> DELETE FROM employee; SQL> DELETE FROM employee WHERE dept_code = 'MKTG';
71 Multi-Table Insert and Delete Multi-table inserts allow a single INSERT INTO .. SELECT statement to conditionally, or non-conditionally, insert into multiple tables.
It reduces table scans and PL/SQL code necessary for performing multiple conditional inserts compared to previous versions.
Prior to Oracle 9i, the only option available was to run separate insert statements, which was a costly option.
There are four kinds of multi-table insert. Unconditional Pivoting Conditional Insert First 72 Multi-Table Insert and Delete Unconditional Insert
Inserts the given data into multiple tables without restrictions.
INSERT ALL
insert All into salary_deduction values(employee_id,ename,tax_ded,pre_tax_ded) into Salary_pay values(employee_id,ename,gross_pay,net_pay) Select a.employee_id,d.ename,gross_pay,a.pre_tax_ded,a.tax_ded,a.net_pay from extern_pay_amount a,emp d where a.employee_id = d.empno / 73 Multi-Table Insert and Delete Pivoting Insert
Is used to insert into the same table multiple times.
INSERT ALL INTO all_paycheck VALUES (emp_id,'JAN',net_pay_jan) INTO all_paycheck VALUES (emp_id,'FEB',net_pay_feb) INTO all_paycheck VALUES (emp_id,'MAR',net_pay_mar) INTO all_paycheck VALUES (emp_id,'APR',net_pay_apr) INTO all_paycheck VALUES (emp_id,'MAY',net_pay_may) INTO all_paycheck VALUES (emp_id,'JUN',net_pay_jun) SELECT emp_id,net_pay_jan, net_pay_feb, net_pay_mar, net_pay_apr, net_pay_may, net_pay_jun FROM monthwise_paycheck_report; 74 Multi-Table Insert and Delete Conditional Insert
Used for conditional control of each insert based on established specific criteria.
INSERT ALL WHEN grade like 'M%' then INTO manager_pay VALUES (employee_id, gross_pay, net_pay) WHEN dept_code like 'GEN' then INTO worker_pay VALUES (employee_id, gross_pay, net_pay) ELSE INTO all_pay VALUES (employee_id, gross_pay, net_pay) SELECT employee_id, gross_pay, net_pay,grade,dept_code FROM extern_pay_amount,employee where extern_pay_amount.employee_id=employee.emp_code 75 Multi-Table Insert and Delete Insert First
Allows for conditional execution of an insert statement based on a series of WHEN clause.
INSERT FIRST WHEN grade like 'M%' then INTO manager_pay VALUES (employee_id, gross_pay, net_pay) WHEN grade like 'E%' then INTO worker_pay VALUES (employee_id, gross_pay, net_pay) else INTO all_pay VALUES (employee_id, gross_pay, net_pay) SELECT employee_id, gross_pay, net_pay,grade FROM extern_pay_amount,employee where extern_pay_amount.employee_id=employee.emp_code; 76 MERGE statement Meaning
MERGE statement allows you to insert a record into a table if it doesn't exist, and it allows you to update an existing record in a table during the execution of the statement.
You can specify conditions to determine whether to update or insert into the target table or view.
Is a convenient way to combine multiple operations.
It lets you avoid multiple INSERT, UPDATE, and DELETE DML statements. 77 MERGE statement Example
MERGE INTO all_pay a USING manager_pay b on (a.emp_id=b.emp_id) when matched then update set a.gross_pay=b.gross_pay,a.net_pay=b.net_pay when not matched then insert values (b.emp_id,b.gross_pay,b.net_pay); 78 Module : Modifying Table Structure Overview Altering Table structure Dropping Column from a Table Dropping a Table 79 Modifying a Table Structure SQL> ALTER table employee ADD (age number (2));
SQL> ALTER table employee MODIFY (age number (3));
SQL> ALTER table employee DROP column sex;
SQL> ALTER table employee DROP (age,married);
80 SQL> DROP table dept;
Dropping a Table DROP TABLE table-name; 81 Module : Integrity Constraints
Overview Understanding Table and Column Constraints Creating, Modifying and Dropping Column level constraints Creating, Modifying and Dropping Table level constraints Adding Constraints to Columns of an existing table Enabling and Disabling Constraints Dropping Columns and Tables having constraints 82 Integrity Constraints Not Null
Unique
Check
Primary Key
Foreign Key
83 Column Constraints SQL> CREATE TABLE employee ( emp_code number (5) NOT NULL, emp_name varchar2 (25) NOT NULL, dept_code varchar2 (4) );
96 Adding Constraints to Columns of an existing Table SQL> ALTER TABLE employee ADD CONSTRAINT emp_dates CHECK (date_join > date_birth);
97 Enabling and Disabling Constraints SQL> alter table dept DISABLE CONSTRAINT cd_pk;
SQL> alter table dept ENABLE CONSTRAINT cd_pk;
SQL> alter table dept DISABLE CONSTRAINT cd_pk CASCADE;
98 13-98 Cascading Constraints Example: ALTER TABLE ord2459 DROP COLUMN order_id CASCADE CONSTRAINTS;
ALTER TABLE test1 DROP (col1_pk, col2_fk, col1) CASCADE CONSTRAINTS;
99 13-99 Renaming Table Columns and Constraints Use the RENAME COLUMN clause of the ALTER TABLE statement to rename table columns.
Use the RENAME CONSTRAINT clause of the ALTER TABLE statement to rename any existing constraint for a table.
ALTER TABLE marketing RENAME COLUMN team_id TO id;
ALTER TABLE marketing RENAME CONSTRAINT mktg_pk TO new_mktg_pk;
a b 100 Dropping a Constraint SQL> alter table employee DROP CONSTRAINT emp_date;
SQL> alter table employee DROP CONSTRAINT emp_date CASCADE;
101 Dropping a Constraint SQL> alter table dept DROP COLUMN dept_code CASCADE CONSTRAINTS;
SQL> drop table dept CASCADE CONSTRAINTS;
102 Module : Sequences & Synonyms
Overview
Creating, altering, dropping and using Sequences Creating, dropping and using Synonyms Querying the data dictionary
103 Sequences CREATE SEQUENCE sequence_name [INCREMENT BY n1] [START WITH n2] [MAXVALUE n3] [MINVALUE n4] [CYCLE | NOCYCLE]; Is a database object which is used to generate automatic unique integer values. 104 Sequences SQL> CREATE SEQUENCE Emp_Number Increment By 2 Start With 3;
106 Sequences SQL> ALTER SEQUENCE emp_number maxvalue 250;
SQL> DROP SEQUENCE emp_number;
107 Synonyms Is an alternative name for another object, which may be a table, view, index or a sequence. CREATE SYNONYM synonym_name FOR table_name 108 Synonyms SQL> CREATE SYNONYM myemp for employee;
SQL> SELECT * FROM myemp;
SQL> DROP SYNONYM myemp;
109 Querying the Data Dictionary For Sequences desc USER_SEQUENCES SELECT * FROM USER_SEQUENCES;
For Synonyms desc USER_SYNONYMS SELECT * FROM USER_SYNONYMS; 110 Module : Indexes
Overview
Understanding Indexes
Unique and Non-unique Indexes Creating and dropping Indexes Querying the Data Dictionary
111 Indexes Are database objects used to improve the performance of the database.
Uses the ROWID for search operations.
There are two types of index: UNIQUE NON UNIQUE
SQL> CREATE UNIQUE INDEX code_idx ON employee(dept_code); CREATE [UNIQUE] INDEX index_name ON table_name (column_name); 112 Indexes SQL> CREATE INDEX cd_idx ON employee (dept_code);
SQL> CREATE INDEX emp_idx ON employee (dept_code, emp_code);
SQL> DROP INDEX cd_idx;
113 Querying the Data Dictionary SQL> desc USER_INDEXES
SQL> SELECT index_name, uniqueness FROM USER_INDEXES WHERE table_name = 'EMPLOYEE';
114 Module : Views
Overview
Understanding Views
Creating views Altering & dropping views Manipulating data using views Querying the Data Dictionary
115 Views SQL> CREATE VIEW fin_emp AS SELECT * FROM employee WHERE dept_code = 'FIN';
SQL> CREATE OR REPLACE VIEW fin_emp AS SELECT * FROM employee;
117 Views SQL> CREATE OR REPLACE view fin_emp AS SELECT * FROM employee with read only;
SQL> DROP VIEW fin_emp;
118 Querying the Data Dictionary SQL> desc USER_VIEWS
SQL> SELECT view_name, text FROM USER_VIEWS; 119 Module :Materialized Views Materialized views are special kind of views, which physically exist inside the database. Their basic purpose is to improve query execution time. The biggest benefits of using materialized views will be seen by users of data warehouse. Oracle makes the task of creating and maintaining summary tables easy, through the concept of materialized views. You can visualize a materialized view to be like any other view, but one which is physically created and allocated space on the disk. Materialized views have values that are stored in them. 120 How Do Materialized Views Work? A materialized view contains the results of a pre-defined query, such as the sum of sales by region over a period of time.
There is no limit to the number of materialized views that may be defined.
When a SQL query is issued, the query rewrite facility within Oracle will determine whether a suitable materialized view is available.
If it is, Oracle will transparently rewrite the query to use the materialized view instead. 121 Materialized Views & Performance They significantly improve performance since the query accesses the small set of rows in the materialized view rather than all the rows in the tables referenced by the query.
They are an extremely important feature for enhancing the performance of complex business intelligence queries.
You can set up the materialized views to be automatically updated when the tables that they are based upon, change.
Or when you explicitly issue a command to refresh them.
This makes the management of the materialized views simpler. 122 Materialized Views & Refresh Methods Whenever the underlying tables of a materialized view are updated, Oracle marks the materialized view as stale.
Unless QUERY_REWRITE_INTEGRITY is set to stale_tolerated, a stale materialized view will not be used by the query rewrite engine.
Oracle provides a mechanism to keep the materialized view fresh with respect to the base tables called materialized view refresh. 123 Materialized Views & Refresh Methods The following types of refresh methods are supported by Oracle. Complete - build from scratch Fast - only apply the data changes Force - try a fast refresh, if that is not possible, do a complete refresh Never - never refresh the materialized view
124 Materialized Views Consider the following query: select prodgr_name, prod_name, sum (target) from prodgrup, product where prodgrup.prodgr_code = product.prodgr_code group by prodgr_name,prod_name; A materialized view for the above can be created as follows: create materialized view product_wise_profit_total build immediate refresh on commit enable query rewrite as select prodgr_name, prod_name, sum (target) from prodgrup, product where prodgrup.prodgr_code = product.prodgr_code group by prodgr_name,prod_name; 125 Materialized Views In the above command : build immediate can be replaced by build deferred refresh on commit can be replaced by refresh on demand enable query rewrite can be replaced by disable query rewrite
126 Module : Transaction Processing COMMIT
ROLLBACK
ROLLBACK TO SAVEPOINT
SAVEPOINT
LOCK TABLE
127 Transaction Processing SQL> SAVEPOINT savepointname; SQL> SAVEPOINT stage1; SQL> ROLLBACK TO savepointname; SQL> ROLLBACK TO stage1;
128 Transaction Processing lock table table_reference_list in lock_mode [nowait]
SQL> LOCK table emp IN ROW EXCLUSIVE MODE;
SQL> LOCK table emp,dept IN SHARE MODE NOWAIT;
SQL> LOCK table scott.emp@new_york IN SHARE UPDATE MODE;
SQL> update employee set salary = (SELECT salary FROM employee WHERE emp_name = 'Manorama Gupta' ) WHERE emp_name = 'Neerja Girdhar'; 129 Module : Formatting the Output Overview
Setting page layout
Formatting column output and spooling
Computing column values at breaks in SQL * Plus
130 Setting Page Layout SQL> set LINESIZE 60;
SQL> set PAGESIZE 20;
SQL> TTITLE 'List of Employees';
SQL> TTITLE 'Pragati Software|List of Employees';
SQL> BTITLE 'Sample Report';
131 Formatting Column Output SQL> SPOOL c:\mydata\output.txt; SQL> COLUMN emp_name FORMAT A10 HEADING 'Employee|Name'; SQL> COLUMN salary FORMAT 9,99,999; SQL> show all;
132 Formatting the Output SQL> SELECT dept_name, emp_name, salary FROM employee, dept WHERE employee.dept_code = dept.dept_code ORDER BY dept_name;
SQL> BREAK ON dept_name;
SQL> SELECT dept_name, emp_name, salary FROM employee, dept WHERE employee.dept_code = dept.dept_code ORDER BY dept_name; 133 Formatting the Output SQL> break on dept_name SKIP 1;
SQL> COMPUTE SUM OF salary on dept_name;
134 Formatting the Output SQL> break on report skip on dept_name skip 2; SQL> show all; 135 MODULE:DROP TABLE PURGE DROP TABLE dept80 PURGE ; 136 MODULE:FLASHBACK TABLE Statement Enables you to recover tables to a specified point in time with a single statement Restores table data along with associated indexes and constraints Enables you to revert the table and its contents to a certain point in time or system change number (SCN)
SCN 137 13-137 FLASHBACK TABLE Statement Repair tool for accidental table modifications Restores a table to an earlier point in time Benefits: Ease of use, availability, and fast execution Is performed in place
Syntax:
FLASHBACK TABLE[schema.]table[, [ schema.]table ]... TO { TIMESTAMP | SCN } expr [ { ENABLE | DISABLE } TRIGGERS ]; 138 Using the FLASHBACK TABLE Statement
DROP TABLE emp2 ;
FLASHBACK TABLE emp2 TO BEFORE DROP;
SELECT original_name, operation, droptime FROM recyclebin ; 139 13-139 MODULE:Temporary Tables When session/transaction completes 140 Creating a Temporary Table CREATE GLOBAL TEMPORARY TABLE cart ON COMMIT DELETE ROWS ; CREATE GLOBAL TEMPORARY TABLE today_sales ON COMMIT PRESERVE ROWS AS SELECT * FROM orders WHERE order_date = SYSDATE ; 1 2 141 MODULE: External Tables 142 Creating a Directory for the External Table Create a DIRECTORY object that corresponds to the directory on the file system where the external data source resides. CREATE OR REPLACE DIRECTORY emp_dir AS '//emp_dir';
GRANT READ ON DIRECTORY emp_dir TO ora_21; 144 13-144 Creating an External Table CREATE TABLE <table_name> ( <col_name> <datatype>, ) ORGANIZATION EXTERNAL (TYPE <access_driver_type> DEFAULT DIRECTORY <directory_name> ACCESS PARAMETERS ( ) ) LOCATION ('<location_specifier>') REJECT LIMIT [0 | <number> | UNLIMITED]; 146 Creating an External Table by Using ORACLE_LOADER CREATE TABLE oldemp ( fname char(25), lname CHAR(25)) ORGANIZATION EXTERNAL ( TYPE ORACLE_LOADER DEFAULT DIRECTORY emp_dir ACCESS PARAMETERS ( RECORDS DELIMITED BY NEWLINE NOBADFILE NOLOGFILE FIELDS TERMINATED BY ' , ' ( fname POSITION ( 1:20 ) CHAR , lname POSITION ( 22:41 ) CHAR ) ) LOCATION ( ' emp.dat ' ) ) PARALLEL 5 REJECT LIMIT 200 ; 148 13-148 Querying External Tables SELECT * FROM oldemp emp.dat OLDEMP 149 Module : Introduction to PL/SQL
Overview
Understanding PL/SQL
PL/SQL data types
Declaring variables
Looping and Conditional constructs
Anchored Data types
150 PL/SQL Facilities provided by PL/SQL Row-level processing Conditional statements (IF...ELSE...END IF, CASE) Looping statements (FOR...NEXT, WHILE...LOOP...END LOOP, etc.) Variable declaration and manipulation Exception handling User-defined procedures which may be called FROM anyWHERE
SQL> update employee set salary = salary + 111 WHERE dept_code = 'MKTG';
151 PL/SQL SQL> begin update employee set salary = salary + 111 where dept_code = 'MKTG'; end;
SQL> @pl_sql_filename; or SQL> run pl_sql_filename;
152 PL/SQL SQL> begin update employee set salary = salary + 111 WHERE dept_code = &deptval; end; SQL> declare nSalary number (6); begin SELECT salary into nSalary FROM employee WHERE emp_code = 11; if nSalary < 8000 then update employee set salary = salary + 101 WHERE emp_code = 11; end if; end; 153 PL/SQL Data Types Scalar Composite Reference LOB 154 Scalar Types Scalar type is a data type that holds a single value. Scalar type includes the following categories: Character / String Number Boolean Date / Time
155 Scalar Types Character / String Allows PL/SQL character or string types. Up to 32 K in size.
Number Allows integer data types.
Boolean Allows TRUE, FALSE or NULL values.
156 Scalar Types Date / Time Include DATE and TIMESTAMP datatypes. DATE type is used to store date. TIMESTAMP is an extension of DATE type. Includes year, month, day, hour, minute, seconds and fraction of second.
157 Scalar Types Timestamp Provides date and time with fraction of seconds up to 9 places. declare v_date timestamp(9) := systimestamp; begin dbms_output.put_line(v_date); end;
158 Scalar Types Timestamp with time zone Is an extension of TIMESTAMP type in that it stores the local timestamp relative to UTC.
declare v_date timestamp(3) with time zone := systimestamp; begin dbms_output.put_line(v_date); end;
159 Scalar Types Timestamp with local time zone Returns time corresponding to the location of the client accessing the database server.
declare v_date timestamp(5) with local time zone := systimestamp; begin dbms_output.put_line(v_date); end;
160 Composite Types Contain internal components Are reusable Are of two types: PL/SQL Records PL/SQL Collections Index By tables Varrays Nested tables Object types 161 Reference Types and LOB Types Reference types provide memory structures
They can point to different storage locations through out the program
Are of two types: Ref Cursor Ref
LOB types are used to work with data types up to 4 GB in size.
162 PL/SQL IF-ELSE Statements if nValue > 40 then nCount := nCount + 1; end if; if nValue > 40 then if nValue < 50 then nCount := nCount + 1; end if; end if; if nValue between 40 and 50 then nCount := nCount + 1; end if;
163 PL/SQL IF-ELSE Statements if nValue > 40 then nCount1 := nCount1 + 1; else nCount2 := nCount2 + 1; end if; if nSalary < 2000 then nProfTax := 0; elsif nSalary < 3500 then nProfTax := 15; elsif nSalary < 5000 then nProfTax := 30; else nProfTax := 50; end if;
164 PL/SQL SQL> declare nSalary number (6); begin SELECT salary into nSalary FROM employee WHERE emp_code <= 11; if nSalary < 8000 then update employee set salary = salary + 101 WHERE emp_code = 11; end if; end;
165 PL/SQL SQL> SELECT ename, ( case deptno when 10 then 'ACCOUNTS' when 20 then 'RESEARCH' when 30 then 'SALES' when 40 then 'OPERATIONS' else 'UNASSIGNED' end ) as Department FROM emp;
166 PL/SQL SQL> SELECT ename,sal,deptno, Case when sal<=500 then 0 when sal>500 and sal<1500 then 100 when sal>=1500 and sal <2500 and deptno=10 then 200 when sal >1500 and sal <2500 and deptno=20 then 500 when sal>=2500 then 300 Else 0 End bonus FROM emp;
167 PL/SQL LOOPS SQL> declare nCode number (5); begin nCode := 101; loop insert into employee (emp_code, emp_name) values (nCode, 'Somebody'); nCode := nCode + 1; if nCode > 110 then exit; end if; end loop; end;
168 PL/SQL LOOPS SQL> declare nCode number (5); begin nCode := 101; while nCode <= 110 loop insert into employee (emp_code, emp_name) values (nCode, 'Somebody'); nCode := nCode + 1; end loop; end;
WHILE condition LOOP statements; END LOOP; 169 SQL> begin for ncode in 101..110 loop insert into employee (emp_code, emp_name) values (ncode, 'somebody'); end loop; end;
PL/SQL LOOPS FOR variable in [REVERSE] lowerbound .. Upperbound LOOP statements; END LOOP;
170 PL/SQL SQL> declare nSalary employee.salary%type; begin SELECT salary into nsalary FROM employee WHERE emp_code = 11;
if nsalary < 8000 then update employee set salary = salary + 101 WHERE emp_code = 11; end if; end;
171 PL/SQL SQL> declare nRecord employee%rowtype; begin SELECT * into nRecord FROM employee WHERE emp_code = 11; if nRecord.salary < 8000 then update employee set salary = salary + 101 WHERE emp_code = 11; end if; end;
recorddatatype.columnname nRecord.Salary
172 PL/SQL SQL> declare nRecord employee%rowtype; nFactor constant number (4, 2) := 1.11; begin SELECT * into nRecord FROM employee WHERE emp_code = 11; if nRecord.salary < 8000 then update employee set salary = salary * nFactor WHERE emp_code = 11; end if; end;
constantname CONST datatype := value;
173 Module : Cursors
Overview
Understanding Cursors
Types of cursors
Cursor operations
Cursor attributes
Parameterized Cursors
Cursor FOR loop
REF Cursors 174 Cursors Provide a subset of data, defined by a query, retrieved into memory when opened, and stored in memory until the cursor is closed.
Point to a memory region in the Process Global Area (PGA) called the context area.
Context area holds: Reference to the rows returned by the query Number of rows processed by the query A pointer to the parsed query in the Shared Pool
Pointer is to memory, not to the data directly.
We are guaranteed a consistent view of data throughout the transaction. 175 Types of Cursors Implicit Cursors
Are implicitly created by PL/SQL, whenever any DML or SELECT....INTO statement is executed in a PL/SQL block.
Explicit Cursors
Are declared and named by the programmer.
The programmer directly controls almost all operations of the cursor.
CURSOR employee_cur IS select * from employee;
OPEN employee_cur;
FETCH employee_cur INTO employee_rec;
CLOSE employee_cur; 176 Implicit Cursors SQL> declare var1 varchar2(30); begin SELECT emp_name INTO var1 FROM employee WHERE emp_code=34; dbms_output.put_line('Value of var1 is : '||var1); end;
178 Implicit Cursors SQL> begin update employee set salary = salary + 100 where dept_code='TRNG'; dbms_output.put_line(SQL%ROWCOUNT || 'rows updated'); if SQL%NOTFOUND then dbms_output.put_line ('Unable to update department TRNG'); end if; end;
179 Explicit Cursors To use an explicit cursor, we have to perform 4 different operations: Declare the cursor Open the cursor Fetch the cursor Close the cursor 180 Explicit Cursors SQL> declare cursor sales is SELECT a.salesman_id,a.salesman_name, b.target, c.sales FROM salesman a, target b, sales c WHERE a.salesman_id=b.salesman_id and b.tmonth=c.smonth; begin .............. end;
181 Explicit Cursors SQL> declare /* explicit declaration of a cursor*/ cursor emptyp_cur is SELECT emptyp.type from employee emp, employee_type emptyp WHERE emp.type_code= emptyp.type_code; begin /* check to see if cursor is already open. If not, open it. checked using %isopen. It is a cursor attribute explained later */ if not emptyp_cur%isopen then open emptyp_cur; end if; /* fetch row FROM cursor directly into an oracle forms item*/ fetch emptyp_cur into :emp.type_desc; /* close the cursor*/ close emptyp_cur; end; 182 Explicit Cursor Operations Cursor Operations Parse Bind Open Execute Fetch Close
183 Explicit Cursor Attributes Name Description %FOUND Returns TRUE if record was fetched successfully, FALSE otherwise. %NOTFOUND Returns TRUE if record was not fetched successfully, FALSE otherwise. %ROWCOUNT Returns number of records fetched FROM the cursor at that point in time. %ISOPEN Returns TRUE if cursor is open, FALSE otherwise
CURSOR caller_cur IS SELECT caller_id, company_id FROM caller;
184 Explicit Cursors SQL> declare cursor caller_cur is SELECT caller_id, company_id FROM caller; caller_rec caller_cur%rowtype; begin /*open the cursor if it is not open*/ if not caller_cur%isopen then open caller_cur; end if; fetch caller_cur into caller_rec; /* keep fetching until no more records are found */ while caller_cur%found loop dbms_output.put_line ('Just fetched record number' || to_char (caller_cur%rowcount)); fetch caller_cur into caller_rec; end loop; close caller_cur; end; 185 Explicit Cursors SQL> declare cursor emp_cur is SELECT * FROM employee; emp_rec emp_cur%rowtype; v_rowcount number :=0; begin if not emp_cur%isopen then open emp_cur; end if; loop fetch emp_cur into emp_rec; dbms_output.put_line(emp_rec.emp_name); v_rowcount := emp_cur%rowcount; exit when emp_cur%notfound; end loop;
186 Explicit Cursors dbms_output.put_line('total rows retrieved are : ' || v_rowcount); close emp_cur; if emp_cur%isopen =false then dbms_output.put_line('cursor closed'); else dbms_output.put_line('the cursor is still open'); end if; end;
187 Explicit Cursors
188 Explicit Cursors SQL> open caller_cur; loop fetch caller_cur into caller_rec; exit when not caller_cur%found; update caller set caller_id=caller_rec.caller_id; WHERE call_timestamp< sysdate; end loop; close caller_cur;
189 Cursors Differences Between Implicit and Explicit Cursor Attributes
If the RDBMS has not opened an SQL cursor in the session, SQL%ROWCOUNT attribute returns NULL. References to other attributes (ISOPEN, FOUND, NOTFOUND) all return FALSE .
The %ISOPEN attribute will always return FALSE before and after the SQL statement.
You must reference the SQL% attribute immediately after you execute the SQL statement.
The %FOUND attribute returns TRUE if an UPDATE, DELETE or INSERT affected at least one record. It will return FALSE if those statements failed to affect any records.
When an implicit SELECT statement does not return any rows, PL/SQL raises NO_DATA_FOUND exception and if more than one row are returned, PL/SQL raises the TOO_MANY_ROWS exception.
190 Parameterized Cursors Provide a way to pass information into and out of a module.
Makes a cursor more reusable.
Makes the cursor more generalized. 191 Parameterized Cursors SQL> declare CURSOR employee_cur(dept_desc varchar2) IS SELECT emp_name,salary,dept_code FROM employee WHERE dept_code= upper(dept_desc); emp_rec employee_cur%rowtype; begin open employee_cur('&dept_desc'); fetch employee_cur into emp_rec; DBMS_OUTPUT.PUT_LINE(emp_rec.emp_name|| ' ' ||emp_rec.salary|| ' ' ||emp_rec.dept_code); end;
192 Cursor FOR Loop Is associated with an explicit cursor or a SELECT statement embedded directly within a loop.
Does not require an explicit OPEN, FETCH or, CLOSE.
PL/SQL handles its processing.
The variable declared in the FOR loop need not be declared.
193 Cursor FOR Loop SQL> declare CURSOR c1 IS SELECT emp_name, dept_code FROM employee WHERE dept_code LIKE '%FI%'; begin FOR item IN c1 loop dbms_output.put_line('Name = ' || item.emp_name || ', Department code = ' || item.dept_code); end loop; end; 194 REF Cursors REF Cursors offer a dynamic and persistent cursor alternative to the static explicit cursors.
Are evaluated at run time instead of compile time.
Can be opened for multiple SELECT statements in the same block.
That is, a single cursor variable can be used to fetch from different result sets.
REF Cursors can be either strongly typed or weakly typed.
195 REF Cursors Declaring REF CURSOR types and Cursor Variables:
TYPE company_curtype is REF CURSOR RETURN company%rowtype;
TYPE generic_curtype is REF CURSOR ;
TYPE cursor_type_name is REF CURSOR [return return_type]; 196 REF Cursors SQL> declare TYPE emp_type is REF CURSOR return employee%rowtype; emp_curv emp_type; v_emp employee%rowtype; begin OPEN emp_curv FOR SELECT * FROM employee WHERE dept_code='FIN'; dbms_output.put_line('-----------------'); dbms_output.put_line('Opened the cursor'); dbms_output.put_line('-----------------'); loop FETCH emp_curv INTO v_emp; EXIT WHEN emp_curv%NOTFOUND; dbms_output.put_line(v_emp.emp_name); end loop; CLOSE emp_curv; 197 REF Cursors OPEN emp_curv FOR select * from employee where dept_code='TRNG'; dbms_output.put_line('-----------------------'); dbms_output.put_line('Opened the cursor again'); dbms_output.put_line('-----------------------'); loop FETCH emp_curv INTO v_emp; EXIT WHEN emp_curv%NOTFOUND; dbms_output.put_line(v_emp.emp_name); end loop; CLOSE emp_curv; END; 198 REF Cursors 199 REF Cursors SQL> declare TYPE emp_type is REF CURSOR; emp_curv emp_type; v_emp employee%rowtype; v_dept dept%rowtype; begin OPEN emp_curv FOR SELECT * FROM employee WHERE dept_code='MKTG'; dbms_output.put_line('-------------------------------'); dbms_output.put_line('Opened the cursor for EMP table'); dbms_output.put_line('-------------------------------'); loop FETCH emp_curv INTO v_emp; EXIT WHEN emp_curv%NOTFOUND; dbms_output.put_line(v_emp.emp_name); end loop; close emp_curv; 200 REF Cursors OPEN emp_curv FOR select * from dept; dbms_output.put_line('--------------------------------'); dbms_output.put_line('Opened the cursor for DEPT table'); dbms_output.put_line('--------------------------------'); loop FETCH emp_curv INTO v_dept; EXIT WHEN emp_curv%NOTFOUND; dbms_output.put_line(v_dept.dept_name); end loop; CLOSE emp_curv; end; 201 REF Cursors
202 Module : Exception Handlers
Overview Understanding exceptions Named system exceptions Unnamed system exceptions Named programmer-defined exceptions Unnamed programmer-defined exceptions
203 Exception Handlers Error Type Reported By How Handled Compile-time PL/SQL Compiler Interactively : compiler reports errors, and you have to correct them. Run-time PL/SQL run-time engine Programmatically : exceptions are raised and caught by exception handlers. Exceptions are errors in a PL/SQL block that are raised during execution of the block. Exceptions can be raised implicitly by the oracle server or explicitly by the application program. An exception handler may be specified to handle the raised exception. Exceptions are raised either at compile time or run time: 204 Exception Handlers Types of exceptions:
Named System exceptions Named Programmer-defined exceptions Unnamed System exceptions Unnamed Programmer-defined exceptions 205 Exception Handlers The Exception Section An English Like Translation EXCEPTION WHEN NO_DATA_FOUND THEN executable_statements1; If the NO_DATA_FOUND exception was raised, then execute the first set of statements. WHEN payment_overdue THEN executable_statements2; If the payment is overdue, then execute the second set of statements WHEN OTHERS THEN executable_statements3; If any other exception is encountered, then execute the third set of statements 206 Exception Handlers declare ...... declarations ...... begin ...... executable statements...... [exception ...... exception handlers......] end; exception when exception_name then <executable statements> end;
207 Exception Handlers Named System Exceptions
Are raised implicitly when its associated Oracle error occurs. Are declared in the STANDARD package.
SQL> declare v_emp emp%rowtype; begin SELECT * into v_emp FROM emp; end;
208 Exception Handlers Name of Exception Oracle Error/SQLCODE Description CURSOR_ALREADY_OPEN ORA-6511 SQLCODE=-6511 You tried to OPEN a cursor that was already OPEN. You must CLOSE a cursor before you try to OPEN or re-OPEN it. DUP_VAL_ON_INDEX ORA-00001 SQLCODE=-1 Your INSERT or UPDATE statement attempted to store duplicate values in a column or columns in a row, which is restricted by a unique index. INVALID_CURSOR ORA-01001 SQLCODE=-1001 You made reference to a cursor that did not exist. This usually happens when you try to FETCH FROM a cursor or CLOSE a cursor before that cursor is OPENed. INVALID_NUMBER ORA-01722 SQLCODE=-1722 PL/SQL executes a SQL statement that cannot convert a character string successfully to a number. This exception is different FROM the VALUE_ERROR exception, as it is raised only FROM within a SQL statement. LOGIN_DENIED ORA-01017 SQLCODE=-1017 Your program tried to log onto the Oracle RDBMS with an invalid username-password combination. This exception is usually encountered when you embed PL/SQL in 3GL language. NO_DATA_FOUND ORA-01403 SQLCODE=+100 This exception is raised in three different scenarios: (1) You executed a SELECT INTO statement(implicit cursor) that returned no rows. (2) You referenced an uninitialized row in a local PL/SQL table. (3) You read past end of file with UTL_FILE package. 209 Exception Handlers NOT_LOGGED_ON ORA-01012 SQLCODE=-1012 Your program tried to execute a call to the database (usually with a DML statement) before it had logged into the Oracle RDBMS. PROGRAM_ERROR ORA-06501 SQLCODE=-6501 PL/SQL encounters an internal problem. The message text usually also tells you to Contact Oracle Support. STORAGE_ERROR ORA-06500 SQLCODE=-6500 Your program ran out of memory or memory in some was corrupted. TIMEOUT_ON_RESOURCE ORA-00051 SQLCODE=-51 A timeout occurred in the RDBMS while waiting for a resource. 210 Exception Handlers Name of Exception Oracle Error/SQLCODE Description TRANSACTION_BACKED_OUT ORA-00061 SQLCODE=-61 The remote part of a transaction is rolled back, either with an explicit ROLLBACK command or as a result of some other action VALUE_ERROR ORA-06502 SQLCODE=-6502 PL/SQL raises a VALUE_ERROR whenever it encounters an error having to do with the conversion, truncation or invalid constraining of numeric and character data. This is a very general and common exception. If this same type of error is encountered in a SQL DML statement within a PL/SQL block, then the INVALID_NUMBER exception is raised. ZERO_DIVIDE ORA-01476 SQLCODE=-1476 Your program tried to divide by zero. 211 Exception Handlers SQL> declare name varchar2(30); begin SELECT emp_name into name FROM employee WHERE emp_code = &emp_code; dbms_output.put_line(name); exception when no_data_found then dbms_output.put_line ('Such employee does not exists'); when others then dbms_output.put_line (SQLERRM || ' '||SQLCODE); dbms_output.put_line ('Some other error'); end; 212 Exception Handlers Named Programmer-Defined Exceptions SQL> declare acbalance number (6); neg_bal exception; begin SELECT balance into acbalance FROM accounts WHERE balance <= 250; if acbalance < 0 then raise neg_bal; end if; exception when neg_bal then update accounts set fine = fine * 5 WHERE ac_type = 'cur'; end; 213 Exception Handlers SQL> declare current_sal number; emp_id number; sal_null exception; begin emp_id:=&empno; SELECT salary into current_sal FROM employee WHERE emp_code=emp_id; if current_sal is null then raise sal_null; else update employee set salary = current_sal+1000 WHERE emp_code = emp_id; end if;
214 Exception Handlers exception when sal_null then dbms_output.put_line('Salary is missing'); end;
215 Exception Handlers Unnamed System Exceptions Are standard Oracle server errors but, are not defined. Also known as non-predefined Oracle errors. Can be trapped by explicitly declaring it first with the PRAGMA EXCEPTION_INIT keyword.
216 Exception Handlers declare exception_name exception; pragma exception_init (exception_name,error_code_literal); begin ........... executable statements ........... raise exception_name; exception when exception_name then ........... executable statements ........... end; 217 Exception Handlers SQL> declare e_missing exception; pragma exception_init (e_missing,-1400); begin insert into new1(empno) values (null); exception when e_missing then dbms_output.put_line('ora-1400 occurred'); end;
218 Exception Handlers raise_application_error(error_number, message[, {true | false}]); Unnamed Programmer-Defined Exceptions The final type of exception is the unnamed programmer- defined exception. This kind of exception occurs when you need to raise an application specific error FROM within the server and communicate this error back to the client application process. The special procedure RAISE_APPLICATION_ERROR lets us issue user-defined error messages FROM stored subprograms 219 Exception Handlers SQL> declare current_sal number; emp_id number; begin emp_id:=&empno; SELECT salary into current_sal FROM employee WHERE emp_code=emp_id; if current_sal is null then raise_application_error(-20102,'salary is missing'); else update employee set salary=current_sal+1000 WHERE emp_code=emp_id; end if; end; 220 Module : Stored Procedures and Functions
The IN parameter mode is used to pass values to the procedure when invoked. The OUT parameter mode is used to return a values to the caller of the procedure. The IN OUT parameter is used to pass initial values to the procedure when invoked and it also returns updated values to the caller.
224 Stored Procedures SQL> create or replace procedure get_emp_data ( eno in number, ename out varchar2, esal out number) as cursor mycursor (eno number) is SELECT emp_name, salary FROM employee WHERE emp_code = eno; begin open mycursor (eno); fetch mycursor into ename, esal; close mycursor; end; 225 Stored Procedures SQL> create or replace procedure raise_salary (emp_id number, increase number) as current_salary number; begin SELECT salary into current_salary FROM employee WHERE emp_code = emp_id; if current_salary is null then raise_application_error(-20101, 'salary is missing'); else update employee set salary = current_salary +increase WHERE emp_code = emp_id; end if; end raise_salary; 226 Stored Procedures SQL> create or replace procedure update_dept (deptno in varchar2, dname in out varchar2) as begin update dept set dept_name=dname where dept_code=deptno; dbms_output.put_line(deptno ||' ' ||dname); end update_dept; 227 Stored Functions Stored Functions Is similar to stored procedures except that a function returns only a single values.
SQL> create or replace function insert_dept ( dcode varchar2, dname varchar2) return boolean as begin insert into dept values (dcode, dname); return true; exception when others then return false; end; 228 Stored Functions
229 Stored Functions SQL> create or replace function compute_tax (empno number, tax in out number) return number is begin select salary into tax from employee where emp_code=empno; tax := tax * .3; return tax; end; 230 Stored Functions SQL> declare var1 number; var2 number; begin var1 := compute_tax(40,var2); dbms_output.put_line('Tax value is: '||var2); end;
231 Module : Packages Overview Introduction to Packages Package Specification and Body Creating Packages Package Overloading Altering and Dropping Packages Advantages of Packages
232 Introduction to Packages
Packages Is a named PL/SQL block that groups logically related PL/SQL constructs such as: Procedures Functions Cursors Variables and constants Exception definitions PL/SQL Types
Packages cannot be called, passed parameters, or nested.
233 Package Specification and Body PACKAGE name IS -- specification (visible part) -- public type and object declarations -- subprogram specifications END [name]; PACKAGE BODY name IS -- body (hidden part) -- private type and object declarations -- subprogram bodies [BEGIN -- initialization statements] END [name]; 234 Creating Packages SQL> create package emp_actions as procedure hire_employee (empid number, ename varchar2, dept varchar2, grade varchar2, sal number ); procedure fire_employee (empid number); end emp_actions; 235 Creating Packages SQL> create or replace package body emp_actions as procedure hire_employee (empid number, ename varchar2, dept varchar2, grade varchar2, sal number ) is begin insert into employee(emp_code, emp_name, dept_code, grade, salary) values(empid,ename,dept,grade,sal); end hire_employee;
236 Creating Packages procedure fire_employee(empid number) is begin delete from employee where emp_code = empid; end fire_employee; end emp_actions;
237 Creating Packages create or replace package emp_data as procedure open_cv (generic_cv in out sys_refcursor, choice in number); end emp_data;
create or replace package body emp_data as procedure open_cv (generic_cv in out sys_refcursor, choice in number) is begin if choice = 1 then open generic_cv for SELECT * FROM employee;
238 Creating Packages elsif choice = 2 then open generic_cv for SELECT * FROM dept; elsif choice = 3 then open generic_cv for SELECT * FROM salgrade; end if; end open_cv; end emp_data; /
variable x refcursor; exec emp_data.open_cv(:x,1); Print x; 239 Creating Packages Package which has functions for random number generation.
SQL> create or replace package randomnumbers is procedure srand( new_seed in number ); function rand(range in number) return number; end randomnumbers; 240 Creating Packages SQL> create or replace package body randomnumbers is multiplier constant number := 22695477; increment constant number := 1; "2^32" constant number := 2 ** 32; "2^16" constant number := 2 ** 16; Seed number := 1; -- Procedure Srand is used to pass a new_seed number procedure srand( new_seed in number ) is begin
241 Creating Packages Seed := new_seed; --seed is a global variable dbms_output.put_line(seed); end srand; -- Function rand is used to generate a random number function rand(range in number) return number is begin seed := mod( multiplier * seed + increment, "2^32" ); return bitand( seed/"2^16", range); end rand; end randomnumbers;
Select randomnumbers.rand(1234) from dual; 242 Package Overloading Within a package, procedure and functions can be overloaded. This means that there is more than one procedure or function with the same name, but with different parameters. It allows the same function to be applied to objects of different types. This option is useful when you want a subprogram to accept similar sets of parameters that have different datatypes. Makes code maintenance easier. 243 Package Overloading SQL> create or replace package journal_entries as ... procedure journalize (amount real, trans_date varchar2); procedure journalize (amount real, trans_date int); end journal_entries; 244 Package Overloading SQL> create or replace package body journal_entries as ... procedure journalize (amount real, trans_date varchar2) is begin insert into journal values (amount,to_date(trans_date, 'dd-mon-yyyy')); end journalize; 245 Package Overloading procedure journalize (amount real, trans_date integer) is begin insert into journal values (amount, to_date(trans_date, 'j')); end journalize; end journal_entries;
246 Altering and Dropping Packages Altering Packages Just like procedures and functions, packages should be recompiled if their referenced constructs are changed for any reason. ALTER PACKAGE package_name COMPILE; ALTER PACKAGE package_name COMPILE BODY;
Dropping Packages DROP PACKAGE BODY package_name; DROP PACKAGE package_name; 247 Advantages of Packages Advantages of Packages Modularity Easier Application Design Information Hiding Added Functionality Better Performance 248 Advantages of Packages 249 Module : Triggers
Overview
Understanding Triggers Keywords and Parameters Applying Triggers Types of Triggers Expressions in Triggers Conditional Predicates Recompiling and Dropping Triggers
250 Database Triggers A trigger defines an action the database should take when some database related event occurs. It may be used to supplement declarative referential integrity, to enforce complex business rules or to audit changes of data. Uses of Triggers are: Audit Data Modifications Log Events Transparently Enforce Complex Business Rules Derive Column Values Automatically Implement Complex Security Authorizations Maintain Replicate Tables 251 Database Triggers CREATE OR REPLACE TRIGGER [schema] triggername {BEFORE, AFTER} {DELETE, INSERT, UPDATE [OF column,.....]} ON [schema.]tablename [REFERENCING {OLD AS old, NEW AS new}] [FOR EACH ROW [WHEN condition]]
DECLARE Variable declarations; Constant declarations; BEGIN PL/SQL subprogram body; EXCEPTION Exception PL/SQL block; END; 252 Database Triggers OR REPLACE Recreates the trigger if it already exists. This option can be used to change the definition of an existing trigger without first dropping it. Schema Is the schema to contain the trigger. If the schema is omitted, the Oracle engine creates the trigger in the users own schema. Triggername Is the name of the trigger to be created BEFORE Oracle engine fires the trigger before executing the triggering statement. AFTER Oracle engine fires the trigger after executing the triggering statement. DELETE Oracle engine fires the trigger whenever a DELETE statement removes a row FROM the table. INSERT Indicates that the Oracle engine fires the trigger whenever a INSERT statement adds a row to table. UPDATE Indicates that the Oracle engine fires the trigger whenever an UPDATE statement changes a value in one of the columns specified in the OF clause. If the OF clause is omitted, the Oracle engine fires the trigger whenever a UPDATE statement changes a value in any column of the table. 253 Database Triggers ON Specifies the schema and name of the table, which the trigger is to be created. If schema is omitted, the Oracle engine assumes the table is in the user's own schema. A trigger cannot be created on a table in the schema SYS. REFERENCI- NG Specifies correlation names. Correlation names can be used in the PL/SQL block and WHEN clause of a row trigger to refer specifically to old and new values of the current row. The default correlation names are OLD and NEW. If the row trigger is associated with a table named OLD or NEW, this clause can be used to specify different correlation names to avoid confusion between table name and he correlation name. FOR EACH ROW Designates the trigger to be a row trigger. The Oracle engine fires a row trigger once for each row that is affected by the triggering statement and meets the optional trigger constraint defined in the when clause. If this clause is omitted the trigger is a statement trigger WHEN Specifies the trigger restriction. The trigger restriction contains a SQL condition that must be satisfied for the Oracle engine to fir the trigger. This condition must contain correlation names and cannot contain a query. Trigger restriction can be specified only for the row triggers. The Oracle engine evaluates this condition for each row affected by the triggering statement. PL/SQL Block is the PL/SQL block that the Oracle engine executes when the trigger is fired. The PL/SQL block cannot contain transaction control SQL statements (COMMIT, ROLLBACK AND SAVEPOINT) 254 Database Triggers Applying Triggers Triggering Event It can be Insert, Update or Delete statement for a table Trigger Constraint (Optional) A boolean expression for each row trigger specified using a WHEN clause Trigger Action PL/SQL code to be executed when a triggering statement is encountered 255 Database Triggers Types of Triggers The 'time' when the trigger fires BEFORE trigger (before the triggering action). AFTER trigger (after the triggering action) INSTEAD OF trigger (for Views)
The 'item' the trigger fires on Row trigger: once for each row affected by the triggering statement Statement trigger: once for the triggering statement, regardless of the number rows affected
256 Database Triggers BEFORE triggers are used when the trigger action should determine whether or not the triggering statement should be allowed to complete.
By using a BEFORE trigger, you can eliminate unnecessary processing of the triggering statement.
BEORE triggers are used to derive specific column values before completing a triggering INSERT or UPDATE statement.
257 Database Triggers Expressions in Triggers
Help in referring to values in row triggers. Need to use :OLD and :NEW prefixes.
If :NEW.column_name < :OLD.column_name 258 Database Triggers Conditional Predicates
Useful when the trigger fires more than one type of DML operation. Need to use the INSERTING, UPDATING or DELETING clause. These are pre defined PL/SQL Boolean type variables which evaluate to either true or false. IF DELETING ('column_name') THEN 259 Database Triggers SQL> create trigger reorder /* triggering event */ after update of qty_on_hand on inventory -- table for each row /* trigger constraint */ when (new.reorderable = 't') begin /* trigger action */ if :new.qty_on_hand < :new.reorder_point then insert into pending_orders values (:new.part_no, :new.reorder_qty, sysdate); end if; end;
create or replace trigger sal_record after update on employee for each row begin dbms_output.put_line('Trigger fired...'); insert into sal_raise values(:old.emp_code, :old.salary, :new.salary, sysdate); end; 261 Database Triggers Mutating Trigger Example:- SQL> create or replace trigger total_salary after delete or insert or update of dept_code, salary on employee for each row begin --assume dept_code, salary are non-null if (deleting) or (updating and :old.dept_code <> :new.dept_code) then update employee set salary = salary - :old.salary WHERE dept_code= :old.dept_code; end if;
262 Database Triggers if (inserting) or (updating and :old.dept_code <> :new.dept_code) then update employee set salary = salary + :new.salary WHERE dept_code = :new.dept_code; end if; if (updating) and (:old.dept_code = :new.dept_code) and (:old.salary <> :new.salary) then update employee set salary = salary + (:new.salary - :old.salary) WHERE dept_code = :old.dept_code; end if; end; 263 Recompiling and Dropping Triggers Recompiling a trigger Just like procedures, functions and packages, triggers can be recompiled. ALTER TRIGGER trigger_name COMPLIE;
Dropping a trigger DROP TRIGGER trigger_name 264 Module : Records and Tables
Overview Introduction to PL/SQL Records Defining and Declaring PL/SQL Records Initializing, referencing, assigning and comparing Records PL/SQL table of records
265 PL/SQL Records and Tables PL / SQL Records A PL/SQL Record provides the means of defining a programming a structure which is a set of variable types. Record types map to a stored definition of the structure. A record type is a programming structure that mirrors a single row in a table. The attribute %ROWTYPE lets you declare a record that represents a row in a database table. type type_name is record (field_declaration[, field_declaration]...); field_name field_type [[NOT NULL] {:= | DEFAULT} expression] 266 PL/SQL Records and Tables SQL> declare type deptrec is record ( dept_id dept.deptno%type, dept_name varchar2(15), dept_loc varchar2(15) ); 267 PL/SQL Records and Tables SQL> declare type timerec is record ( seconds smallint, minutes smallint, hours smallint);
type flightrec is record ( flight_no integer, plane_id varchar2(10), captain employee, -- declare object passengers passengerlist, -- declare varray depart_time timerec, -- declare nested record airport_code varchar2(10)); 268 PL/SQL Records and Tables SQL> declare type emprec is record ( emp_id integer last_name varchar2(15), dept_num integer(2), job_title varchar2(15), salary real(7,2)); FUNCTION nth_highest_salary (n INTEGER) RETURN EmpRec IS ...
SQL> declare type stockitem is record ( item_no integer(3), description varchar2(50), quantity integer, price real(7,2)); item_info stockitem; -- declare record 269 PL/SQL Records and Tables SQL> declare type emprec is record ( emp_id emp.empno%type, last_name varchar2(10), job_title varchar2(15), salary number(7,2)); ... procedure raise_salary (emp_info emprec);
SQL> declare type timerec is record ( seconds smallint := 0, minutes smallint := 0, hours smallint := 0); 270 PL/SQL Records and Tables SQL> declare type stockitem is record ( item_no integer(3) not null := 999, description varchar2(50), quantity integer, price real(7,2));
record_name.field_name emp_info.hire_date ...
To refer to fields in the record that is returned by a function: function_name(parameters).field_name 271 PL/SQL Records and Tables SQL> declare type emprec is record(emp_id number(4),job_title char(14),salary real); middle emprec; middle_sal real; function nth_highest_sal (n integer) return emprec is emp_info emprec; begin emp_info.emp_id:=10; emp_info.job_title:='Working'; emp_info.salary:=1000; return emp_info; -- return record end; begin middle := nth_highest_sal(10);--call function middle_sal :=nth_highest_sal(10).SALARY; --call function dbms_out.put_line(middle_sal); end ; 272 PL/SQL Records and Tables SQL> declare type timerec is record ( minutes smallint, hours smallint); type agendaitem is record ( priority integer, subject varchar2(100), duration timerec); function item (n integer) return agendaitem is item_info agendaitem; begin ... return item_info; -- return record end; begin ... if item(3).duration.minutes > 30 then ... -- call function 273 PL/SQL Records and Tables SQL> declare type flightrec is record ( flight_no integer, plane_id varchar2(10), captain employee, -- declare object passengers passengerlist, -- declare varray depart_time timerec, -- declare nested record airport_code varchar2(10)); flight flightrec; begin . .. if flight.captain.name = 'H Raowlings' then ... 274 PL/SQL Records and Tables record_name.field_name := expression; emp_info.ename := UPPER(emp_info.ename); 275 PL/SQL Records and Tables SQL>declare type deptrec is record ( dept_num number(2), dept_name char(14), location char(13)); type deptitem is record ( dept_num number(2), dept_name char(14), location char(13)); dept1_info deptrec; dept2_info deptitem; begin ... dept2_info := dept1_info; -- illegal; different datatypes 276 PL/SQL Records and Tables SQL> declare type deptrec is record ( dept_num number(2), dept_name char(14), location char(13)); dept_info deptrec; begin SELECT deptno, dname, loc into dept_info FROM dept WHERE ... insert into dept values (dept_info); -- illegal record_name := (value1, value2, value3, ...); -- illegal 277 PL/SQL Records and Tables SQL> Declare type timerec is record (minutes smallint, hours smallint); type meetingrec is record ( day date, time timerec, -- nested record room_no integer(4)); type partyrec is record ( day date, time timerec, -- nested record place varchar2(25)); seminar meetingrec; party partyrec; Begin ... party.time := seminar.time;/*Allowed*/ 278 PL/SQL Records and Tables Records cannot be tested for nullity, equality, or inequality.
SQL> begin ... if emp_info is null then ... -- illegal if dept2_info > dept1_info then ... -- illegal
279 PL/SQL Records and Tables Collect accounting figures FROM database tables assets and liabilities Then use ratio analysis to compare the performance of two subsidiary companies SQL> declare type figuresrec is record (cash real, notes real, ...); sub1_figs figuresrec; sub2_figs figuresrec; ... function acid_test (figs figuresrec) return real is ... begin SELECT cash, notes, ... into sub1_figs FROM assets, liabilities WHERE assets.sub = 1 and liabilities.sub = 1; SELECT cash, notes, ... into sub2_figs FROM assets, liabilities WHERE assets.sub = 2 and liabilities.sub = 2; if acid_test(sub1_figs) > acid_test(sub2_figs) then ... ... end; 280 PL/SQL Records and Tables SQL> create package emp_actions as -- specification type emprectyp is record (empid number, sal number); cursor desc_salary return emprectyp; procedure hire_employee ( empid number, ename varchar2, dept varchar2, grade varchar2, sal number ); procedure fire_employee (empid number); end emp_actions; 281 PL/SQL Records and Tables SQL> create package body emp_actions as -- body cursor desc_salary return emprectyp is select empno, sal from emp order by sal desc; procedure hire_employee ( empid number, ename varchar2, dept varchar2, grade varchar2, sal number ) is 282 PL/SQL Records and Tables begin insert into employee(emp_code, emp_name, dept_code, grade, salary) values(empid,ename,dept,grade,sal);
end hire_employee; procedure fire_employee (empid number) is begin delete from employee where emp_code = empid; end fire_employee; end emp_actions;
283 PL/SQL Records and Tables TYPE <table_name> IS TABLE OF <datatype> [NOT NULL] INDEX BY BINARY INTEGER;
type company_keys_tabtype is table of company.company_id%type not null index by binary integer;
type reports_requested_tabtype is table of varchar2 (100) index by binary integer; PL / SQL Tables A PL/SQL table is a one-dimensional, unbounded collection of homogeneous elements, indexed by integers. It is like an array. 284 PL/SQL Records and Tables <table_name> <table_type>
SQL> declare type countdown_tests_tabtype is table of varchar2 (20) index by binary_integer; countdown_tests_list countdown_tests_tabtype;
begin countdown_tests_list (1) := 'all systems go'; countdown_tests_list (2) := 'internal pressure'; countdown_tests_list (3) := 'engine inflow'; end; 285 PL/SQL Records and Tables type local_emp_table is table of employee%rowtype index by binary_integer; cursor emp_cur is SELECT * FROM employee;
type cursor_emp_table is table of emp_cur%rowtype index by binary_integer; type emp_rectype is record (employee_id integer, emp_name varchar2(60)) ;
type emp_table is table of emp_rectype index by binary_integer; 286 PL/SQL Records and Tables <table_name>(<index_ expression).<field_name> emp_tab(375).emp_name := 'SALIMBA'; Operator Description COUNT Returns the number of elements currently contained in the PL/ SQL table. DELETE Deletes one or more elements FROM the PL /SQL table. EXISTS Returns FALSE if a reference to an element at the specified index would raise the no_data_found exception. FIRST Returns the smallest index of the PL/SQL table for which an element is defined. LAST Returns the greatest index of the PL/SQL table for which an element is defined. NEXT Returns the smallest index of the PL/SQL table containing an element which is greater than the specified index. PRIOR Returns the greatest index of the PL/SQL table containing an element which is less than the specified index. 287 PL/SQL Records and Tables An operation which takes no arguments <table name>.<operation> An operation which takes a row index for an argument. <table name>.<operation>(<index number> [, <index number]) Total_rows := emp_table.COUNT; Names_tab.DELETE; IF seuss_characters_table.EXISTS(1) THEN First_entry_row := employee_table.FIRST; Last_entry_row := employee_table.LAST; Next_index := employee_table.NEXT (curr_index); Prev_index := employee_table.PRIOR (curr_index); Next_index := employee_table.NEXT (curr_index); 288 Module : More on Records and Collections Overview
Inserting PL/SQL records into the database Updating the database with PL/SQL record values Restrictions on record inserts / updates Querying data into collection of records Associative arrays
289 More on Records and Collections Inserting PL/SQL records into the database :
PL/SQL allows the use of %ROWTYPE to insert records into the database.
290 More on Records and Collections SQL> declare dept_info department%rowtype; begin -- dept_code, dept_name are the table columns. -- the record picks up these names FROM the %rowtype. dept_info.dept_code := 'new'; dept_info.dept_name := 'newdept'; -- using the %rowtype means we can leave out the column list -- (dept_code, dept_name) FROM the insert statement. insert into department values dept_info; end; 291 More on Records and Collections Updating the database using PL/SQL record values : The keyword ROW is allowed only on the left side of a SET clause. The argument to SET ROW must be a real PL/SQL record, not a subquery that returns a single row. The record can also contain collections or objects. SQL> declare dept_info department%rowtype; begin dept_info.dept_code := 'new'; dept_info.dept_name := 'newdepartment'; -- The row will have values for the filled-in columns, and null -- for any other columns. update department set row = dept_info WHERE dept_code = 'new'; end; 292 More on Records and Collections Using the RETURNING clause with a record : Returns column values FROM the affected row into a PL/SQL record SQL> declare type emprec is record (emp_name employee.emp_name%type, salary employee.salary%type); emp_info emprec; emp_id number := 10; begin update employee set salary = salary * 1.1 WHERE emp_code = emp_id returning emp_name, salary into emp_info; dbms_output.put_line('just gave a raise to ' || emp_info.emp_name || ', who now makes ' || emp_info.salary); rollback; end; 293 More on Records and Collections Restrictions on record Inserts / Updates : Record variables are allowed only in the following places: On the right side of the SET clause in an UPDATE statement In the VALUES clause of an INSERT statement In the INTO subclause of a RETURNING clause Record variables are not allowed in a SELECT list, WHERE clause, GROUP BY clause, or ORDER BY clause. The following are not supported: Nested record types Functions that return a record Record inserts/updates using the EXECUTE IMMEDIATE statement.
294 More on Records and Collections Querying data into collection of records : Use the BULK COLLECT clause with a SELECT INTO or FETCH statement to retrieve a set of rows into a collection of records SQL> declare type employeeset is table of employee%rowtype; underpaid employeeset;-- holds rows FROM employee table. cursor c1 is SELECT emp_code, emp_name FROM employee; type nameset is table of c1%rowtype; some_names nameset; --holds partial rows FROM employee table. begin -- with one query, we bring all the relevant data into the collection of records. SELECT * bulk collect into underpaid FROM employee WHERE salary < 2500 ORDER BY salary desc; 295 More on Records and Collections
-- Now we can process the data by examining the collection, or passing it to -- a separate procedure, instead of writing a loop to FETCH each row. dbms_output.put_line(underpaid.count || ' people make less than 2500.'); for i in underpaid.first .. underpaid.last loop dbms_output.put_line(underpaid(i).emp_name || ' makes ' || underpaid(i).salary); end loop;
296 More on Records and Collections -- We can also bring in just some of the table columns. -- Here we get the first and last names of 10 arbitrary employees. SELECT emp_code, emp_name bulk collect into some_names FROM employee WHERE rownum < 11; for i in some_names.first .. some_names.last loop dbms_output.put_line('employee = ' || some_names(i).emp_code || ' ' || some_names(i).emp_name); end loop; end;
297 More on Records and Collections Associative Arrays are sets of key-value pairs WHERE each key is unique and is used to locate a corresponding value in the array. The key can be an integer or a string. SQL> declare type population_type is table of number index by varchar2(64); country_population population_type; continent_population population_type; howmany number; which varchar2(64); begin country_population('greenland') := 100000; --creates new entry country_population('iceland') := 750000; -- creates new entry 298 More on Records and Collections -- looks up value associated with a string howmany := country_population('greenland'); continent_population('australia') := 30000000; continent_population('antarctica') := 1000; -- creates new entry continent_population('antarctica') := 1001; -- replaces previous value -- returns 'antarctica' as that comes first alphabetically. which := continent_population.first; dbms_output.put_line(which); -- returns 'australia' as that comes last alphabetically. which := continent_population.last; dbms_output.put_line(which); -- returns the value corresponding to the last key howmany := continent_population(continent_population.last); end; 299 More on Records and Collections Choosing Which PL/SQL Collection Types to Use Arrays in other languages become varrays in PL/SQL. Sets and bags in other languages become nested tables in PL/SQL. Hash tables and other kinds of unordered lookup tables in other languages become associative arrays in PL/SQL.
Choosing Between Nested Tables and Associative Arrays Nested tables can be stored in a database column, but associative arrays cannot. Nested tables can simplify SQL operations WHERE you would normally join a single-column table with a larger table. Associative arrays are appropriate for relatively small lookup tables WHERE the collection can be constructed in memory each time a procedure is called or a package is initialized. Their index values are more flexible, because associative array subscripts can be negative, can be nonsequential, and can use string values instead of numbers.
300 More on Records and Collections Choosing Between Nested Tables and Varrays Varrays are a good choice when: The number of elements is known in advance. The elements are usually all accessed in sequence. When stored in the database, varrays keep their ordering and subscripts. Each varray is stored as a single object, either inside the table of which it is a column (if the varray is less than 4KB) or outside the table but still in the same tablespace (if the varray is greater than 4KB).
Nested tables are a good choice when: The index values are not consecutive. There is no predefined upper bound for index values. You need to delete or update some elements, but not all the elements at once. You would usually create a separate lookup table, with multiple entries for each row of the main table, and access it through join queries. Nested tables can be sparse 301 More on Records and Collections TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY [PLS_INTEGER | BINARY_INTEGER | VARCHAR2(size_limit)]; INDEX BY key_type; Associative array : An initialization clause is not allowed. There is no constructor notation for associative arrays. PLS_INTEGER To store signed integers. Its magnitude range is -2**31 .. 2**31. Require less storage than NUMBER values. PLS_INTEGER operations use machine arithmetic, so they are faster than NUMBER and BINARY_INTEGER operations PLS_INTEGER and BINARY_INTEGER are not fully compatible. When a PLS_INTEGER calculation overflows, an exception is raised. When a BINARY_INTEGER calculation overflows, no exception is raised if the result is assigned to a NUMBER variable. 302 More on Records and Collections Using an Associative array :
SQL> declare type emptabtyp is table of employee%rowtype index by pls_integer; emp_tab emptabtyp; begin /* retrieve employee record. */ SELECT * into emp_tab(10) FROM employee WHERE emp_code = 10; end; 303 More on Records and Collections collection_name(subscript) := expression; Assigning Collections : 304 More on Records and Collections Data type compatibility for collection assignment : Collections must have the same data type for an assignment to work
SQL> declare type last_name_typ is varray(3) of varchar2(64); type surname_typ is varray(3) of varchar2(64); -- these first two variables have the same data type. group1 last_name_typ := last_name_typ('jones','wong','marceau'); group2 last_name_typ := last_name_typ('klein','patsos','singh'); -- this third variable has a similar declaration, but is not the same type. group3 surname_typ := surname_typ('trevisi','macleod','marquez'); begin -- allowed because they have the same data type group1 := group2; -- not allowed because they have different data typess -- group3 := group2; end; 305 More on Records and Collections Assigning a null value to a nested table : Assigning an automically null (unintialised)nested table or varray to a second nested table or varray Assigning the value NULL to acollection. SQL> declare type colors is table of varchar2(64); -- this nested table has some values. crayons colors := colors('silver','gold'); -- this nested table is not initialized ("atomically null"). empty_set colors; begin -- at first, the initialized variable is not null. if crayons is not null then dbms_output.put_line('ok, at first crayons is not null.'); end if; 306 More on Records and Collections --Then we assign a null nested table to it. crayons := empty_set; crayons := null; -- now it is null. if crayons is null then dbms_output.put_line('ok, now crayons has become null.'); end if; -- we must use another constructor to give it some values. crayons := colors('yellow','green','blue'); end; Assigning a value to a collection element can cause various exceptions: Subscript is null or is not convertible to the right data type, VALUE_ERROR. Subscript refers to an uninitialized element, SUBSCRIPT_BEYOND_COUNT. Collection is automically null, COLLECTION_IS_NULL. 307 Module : Bulk Binds
Overview Introduction to Bulk Binds Improving performance using bulk binds Querying data into collections of records Using DML on collections with deleted elements Using DML on selected elements in collections Effects of rollback on FORALL 308 Bulk Binds The switch from PL/SQL engine to SQL engine is called context switch. Context switch degrades the performance of the PL/SQL block or subprogram. In order to avoid a context switch, bulk binding is used. The example on the next slide illustrates a context switch.
309 Bulk Binds To illustrate a context switch : declare type numlist is varray(20) of number; depts numlist := numlist(10, 30, 70, ...); -- department numbers begin .. for i in depts.first..depts.last loop delete FROM emp WHERE depto = depts(i); end loop; end;
In the example above the context switch occurs for every iteration of the loop. To avoid it and improve the performance of block Bulk Binding is used. Assigning of values to PL/SQL variables in SQL statements is called Binding. Binding of entire collection at once is called Bulk Binding. 310 Bulk Binds FORALL index IN lower_bound..upper_bound sql_statement; Improving the performance using bulk bind : To bulk-bind input collections, use the FORALL statement. SQL> declare type numlist is table of number; mgrs numlist := numlist(7566, 7782, ...) -- manager numbers begin ... forall i in mgrs.first..mgrs.last delete FROM emp WHERE mgr = mgrs(i); end; 311 Bulk Binds Although FORALL statement contains an iteration scheme ,it is not a FOR loop.
The index can be referenced only within the FORALL statement and only as a collection subscript.
It can only repeat a single DML statement
The DML statement can reference more than one collection, but FORALL only improves performance WHERE the index value is used as a subscript.
All collection elements in the specified range must exist. If an element is missing or was deleted, you get an error.
The FORALL statement iterates over the index values specified by the elements of this collection 312 Bulk Binds Issuing DELETE statement in a loop : CREATE TABLE employees2 as SELECT * FROM emp;
declare type numlist is varray(20) of number; depts numlist := numlist(10, 30, 70); -- department codes begin forall i in depts.first..depts.last delete FROM employees2 WHERE deptno = depts(i); commit; end; select * from emp minus select * from employees2; 313 Bulk Binds Drop Table Employees2
SQL> CREATE TABLE parts2 (pnum integer, pname varchar2(15)); 314 Bulk Binds SQL> declare type numtab is table of parts1.pnum%type index by pls_integer; type nametab is table of parts1.pname%type index by pls_integer; pnums numtab; pnames nametab; iterations constant pls_integer := 500; t1 integer; t2 integer; t3 integer; begin for j in 1..iterations loop -- load index-by tables pnums(j) := j; pnames(j) := 'part no. ' || to_char(j); end loop;
315 Bulk Binds t1 := dbms_utility.get_time; for i in 1..iterations loop -- use for loop insert into parts1 values (pnums(i), pnames(i)); end loop; t2 := dbms_utility.get_time; forall i in 1..iterations -- use forall statement insert into parts2 values (pnums(i), pnames(i)); t3 := dbms_utility.get_time; dbms_output.put_line('execution time (secs)'); dbms_output.put_line('---------------------'); dbms_output.put_line('for loop: ' || to_char((t2 - t1)/100)); dbms_output.put_line('forall: ' || to_char((t3 - t2)/100)); commit; end;
316 Bulk Binds SQL> DROP TABLE parts1;
SQL> DROP TABLE parts2;
317 Bulk Binds Using FORALL with part of a collection : SQL> CREATE TABLE employees2 as SELECT * FROM emp; SQL> declare type numlist is varray(10) of number; depts numlist := numlist(5,10,20,30,50,55,57,60,70,75); begin forall j in 4..7 -- use only part of varray delete from employees2 where deptno = depts(j); commit; end; SQL> drop table employees2; 318 Bulk Binds How FORALL affects rollback : If any execution of the SQL statement raises an unhandled exception, all database changes made during previous executions are rolled back. If a raised exception is caught and handled, changes are rolled back to an implicit savepoint marked before each execution of the SQL statement. SQL> CREATE TABLE emp2 (deptno number(2), job varchar2(18)); SQL> declare type numlist is table of number; depts numlist := numlist(10, 20, 30); begin insert into emp2 values(10, 'clerk'); insert into emp2 values(20, 'bookkeeper'); -- lengthening this job title causes an exception. insert into emp2 values(30, 'analyst'); commit; 319 Bulk Binds forall j in depts.first..depts.last -- run 3 update statements. update emp2 set job = job || ' (senior)' WHERE deptno = depts(j); -- raises a "value too large" exception exception when others then dbms_output.put_line('problem in the forall statement.'); commit; -- commit results of successful updates. end;
SQL> drop table emp2; 320 Bulk Binds BULK COLLECT INTO collection_name [,collection _name] SQL> declare type numtab is table of emp.empno%type; type nametab is table of emp.ename%type; enums numtab; -- no need to initialize names nametab; begin SELECT empno, ename bulk collect into enums, names FROM emp; ... end; To bulk-bind output collections, use the BULK COLLECT clause 321 Bulk Binds Using with FETCH INTO statement
SQL> declare type nametab is table of emp.ename%type; type saltab is table of emp.sal%type; names nametab; sals saltab; cursor c1 is SELECT ename, sal FROM emp WHERE sal > 1000; begin open c1; fetch c1 bulk collect into names, sals; ... end; 322 Bulk Binds Using with RETURNING INTO caluse
SQL> declare .. begin
forall j in depts.first..depts.last delete FROM emp WHERE empno = depts(j) returning empno bulk collect into enums; . end ;