Oracle Notes

Published on June 2016 | Categories: Documents | Downloads: 71 | Comments: 0 | Views: 267
of 274
Download PDF   Embed   Report

Oracle basic concepts

Comments

Content


1



ORACLE SQL AND PL/SQL NOTES

2

SR NO. Chapter Page no
1 Oracle Database Concept 5
2 Categories of SQL Statements 9
3 Database Objects 11
4 Data Dictionary 11
5 Data Types 12
6 SQL Functions 29
7 Single Row Functions 30
8 Character Functions 31
9 Numeric Functions 42
10 Date Functions 45
11 Conversion Functions 50
12 Aggregate Functions 61
13 Clause (Distinct, Having, Group by, Order by ) 64
14 Set Operator 66
15 Joins 72
16 Sub-Queries 85
17 Co-Related Subquery 89
18 Integrity Constraints 91
19 Index 109
20 Views 111
21 PL/SQL Basics 116
22 %Type 120
23 %Rowtype 124
24 Record Types 126
25 Nested Record Types 128
26 Nested PL/SQL Blocks 136
27 Cursors 142
28 Static Cursor 142
29 For Update (in Cursor) 152
30 Current Of 153
3

SR NO. Chapter Page no
31 Cursor and Memory Management 155
32 Exception Handling 156
33 User-Defined Exceptions 163
34 Sub-Programs 168
35 Procedures Examples 169
36 Function Examples 172
37 Parameter Passing Mode 174
38 Stored Procedures 179
39 Stored Functions 184
40 Raise Application Error 188
41 Packages 190
42 Ref Cursor 195
43 Advantages of Packages 198
44 Database Trigger 200
45 Trigger Cascading 207
46 Instead of Triggers 208
47 Autonomous Transaction 210
48 Native Dynamic SQL 212
49 Object Oriented Concepts 219
50 Object Type 219
51 Nested Object Type 222
52 Collector Types 224
53 Nested Tables 227
54 Collector Methods 230
55 Bulk Binding 231
56 Bulk Collect Clause 235
57 Database Internal Concept 239
58 Oracle Database Structure 239
59 Memory Architecture 250
60 Processes 252
4



61 Role and Privileges 256
62 Object Privileges 257
63 Distributed Database System 259
64 Clusters 260
65 Temporary Tables 261
66 Materialize View 262
67 List of Predefined Packages 264
68 Index Organized Table 264
69 No Copy Compiler hint 265
70 BitMap Index 266
71 SDLC Stages 267
72 Performance Tuning 267
73 Normalization 269
5

Table of Contents
 What is DBMS?
 Drawbacks of file management system
 What is Database?
 Models used for DBMS
 RDBMS’s used in the market
 C/S (Two Tier) Architecture
 N Tier Architecture
 Syllabus and Important topics
 SQL (Structured Query Language)
 Categories of SQL statements
 Database Objects
 Object Naming Rules and Guidelines
 Data Dictionary
 Data Types

What is Database and DBMS?
1. It is a collection of logically related data stored in a specific format
2. What is Data? What is information?
3. Drawbacks of file management systems
 Duplication of Data
 Data integrity problem
 Lengthy processing time
 Lengthy code, increased development costs
 High maintenance costs as complex to change
4. DBMS (Database Management System)






Application
Database DBMS
6


Models used for DBMS
Model determine how data is organized in the disk
The following models are used for DMBS:-
 Hierarchic Model (HDBMS)
 Network Model (NDBMS)
 Relations Model (RDBMS)
 Object Model (OODBMS)
Hierarchic Model
The Hierarchical model was developed by IBM in 1968
One to Many relationship (parent node has the links to its child nods).
SYSTEM2000 is an example of hierarchical database
IBM’s Information Management System (IMS).
If we want to search a record, we have to traverse the tree from the root through all its parent nodes
to reach the specific record. Thus, Searching for a record is very time consuming. This model uses
pointers to navigate between stored data.
Network Model
 In 1971, the conference on Data Systems Languages (CODASYL)
formally defined the network model
 Many to Many relationship
 DBTG codasyl was the first network database
 Simplified searching as record has many access paths
 This model uses pointer to navigate between stored data
Relational Model

EMPNO ENAME SAL
1001 SACHIN 50000
1002 SAURAV 35000
 Introduced by Ted codd, IBM Researcher, in 1970
 Database is a collection of normalized relations
Attributes
Tuples
7

 Relation is a collection of tuples and attributes
 Every relation is independent
 Built in query language support(SQL)
Different RDBMS’s
RDBMS Vendors RDBMS
Computer Associates INGRES
IBM DB2
Informix Software INFORMIX
Oracle Corporation Oracle
Microsoft Corporation MS Access
Microsoft Corporation SQL Server
MySQL AB MySQL
PostgreSQL Dvlp Grp PostgreSQL
Sybase Sybase11

C/S (Two Tier) Architecture













8

N Tier Architecture













SQL (Structured Query Language)
History
1) Developed at IBM by Donald D. Chamberlin and Raymond F. Boyce in the early 1970
2) Initially Called SEQUEL (Structured English Query Language)
3) Designed to manipulate and retrieve data stored in IBM’s original Relational database management
system, System R
4) later Changed to SQL because “SEQUEL” was a trademark of the UK-based Hawker Siddeley aircraft
company
5) Relation software, Inc. Introduced the first commercially available implementation of SQL, Oracle V2
(Version2)
It is an Interface between database and requestor


9

Categories of SQL Statements
 Data Definition Statements (DDL)
 Used to Create and maintain database objects
 CREATE, ALTER, DROP, RENAME, TRUNCATE

 Data Manipulation Statements (DML)
 Used to manipulate the data stored in the database
 INSERT, UPDATE, DELETE

 Data Query Statement (DQL)
 Used to retrieve the data stored in the database
 SELECT

 Data Control Statements (DCL)
 Used to manage / control the privileges
 GRANT, REVOKE

 Transaction Control Statements (TCL)
 Used to manage the transaction
 COMMIT, ROLLBACK, SAVEPOINT, SET TRANSACTION

 What is Transaction
 It is a logical UNIT of a work that contains one or more DML Statements.
 It begins with a DML statement and ends with COMMIT or ROLLBACK.

 Session Control Statements
 They are used to change the properties of the session.
 ALTER SESSION, SET ROLE

 System Control Statements
 It is used to change the properties of the Oracle Instance
 ALTER SYSTEM


10

 What is an INSTANCE
 It is a collection of SGA(System/ Shared Global Area) and Background Process




11

Database Objects
 Oracle Database is a collection of various types of objects
 They are divided into two categories
 Schema Objects
 Non Schema Objects
 Schema
 It is a place where objects created by the user are stored
 Each user has schema by the same name as the user name
 Schema Objects
 If object created by User is stored in his/her own schema then it is called as
schema object
 Non Schema Objects
 Irrespective of the user creating an object, if it is always stored in the schema SYS
Then it is called as Non Schema Object.
Object Naming Rules and Guidelines
1) Name must be 1 to 30 chars long
2) Name must begin with an alphabet
3) Name can contain alpha numeric characters, #, $, or _
4) Name is not case sensitive
5) Reserve keyword cannot be used as a name
6) To ignore rule 2, 3, 4 and 5 name can be enclosed in “ “
7) Name Must be unique within the schema
Guidelines
1. Use Full, descriptive and pronounceable name
2. Use same name to describe same entity/ attribute
Data Dictionary: - It is a Read only set of tables that store following information.
1) The definitions of all schema objects in the database
2) How much has been allocated for, and is currently used by, the schema objects
3) Default values for columns
4) Integrity constraint information
5) The name of Oracle users
12

6) Privileges and roles each user has been granted
7) Auditing information, such as who has accessed or updated various schema
objects.
Data Types
Oracle provides the following categories of built-in data types
1. Character Data Types
2. Numeric Data Types
3. DATE Data type
4. RAW and LONG RAW Data Types
5. ROWID and UROWID Data types
6. LOB Data types
Character Data Types
1. CHAR (NCHAR for supporting Unicode-multi byte)
a. Stores fixed –length character strings
b. Default size 1 char
c. Max size is 2000 chars
d. If you provide shorter value then it is blank-padded to the fixed length
e. If a value is too large, oracle returns an error
f. Oracle compares CHAR values using blank-padded comparison semantics
2. VARCHAR2 (NVARCHAR2 for supporting Unicode-multi byte)
a. Stores variable length character strings
b. Saves on the space used by the table
c. Max size is 4000 chars
d. If a value is too large, Oracle returns an error
e. Oracle compares VARCHAR2 values using Non-padded comparison
semantics

NUMBER
NUMBER (P,S)
 It stores fixed and floating-point, negative numbers
13

 Number having precision P and scale s. The precision p can range from 1 to 38 . the scale s can
range from -84 to 127

Actual Data Specified As Stored As
7456123.89 NUMBER 7456123.89
7456123.89 NUMBER(9) 7456124
7456123.89 NUMBER(9,2) 7456123.89
7456123.89 NUMBER(9,1) 7456123.9
7456123.89 NUMBER(6) Exceeds precision
7456123.89 NUMBER(7,-2) 7456100
7456123.89 NUMBER(7,2) Exceeds precision

DATE
 It stores Century, Year, Month, Day, Hour, Minute, Seconds
 Oracle can store dates in the Julian era, ranging from January 1, 4712 BCE through December 31 4712 CE
(Common Era)
 Date data is stored in fixed-length fields of seven bytes each, corresponding to century, year, month,
day, hour, minute, and second
 For input and output of dates, the standard Oracle date format is DD-MON-YY
 NLS_DATE_FORMAT can be used to change the standard date format
 TO_DATE function with a format mask can be used to INSERT date value in different format than the
standard one
 Default time is 00:00:00 and date is date of first day of current month
LONG
 It used to store the character data up to 2 GB in size
 This data type is provided only for backward compatibility with existing applications
 The use of LONG values is subject to these restrictions:
o A table can contain only one LONG column.
o You cannot create an object type with a LONG attribute.
o LONG columns cannot appear in WHERE clauses or in integrity constraints (except that they can
appear in NULL and NOT NULL constraints).
o LONG columns cannot be indexed.
o LONG data cannot be specified in regular expressions.
o A stored function cannot return a LONG value.
o You can declare a variable or argument of a PL/SQL program unit using the LONG data type.
However, you cannot then call the program unit from SQL.
o In addition , LONG columns cannot appear in these parts of SQL statements
o GROUP BY clauses, ORDER BY clauses, or CONNECT BY clauses or with the DISCTINCT operator in
SELECT statements
o SQL built-in functions, expressions, or conditions
14

o SELECT lists of CREATE TABLE … AS SELECT statements


RAW and LONG RAW Data types
 Used to store binary data
 For example, LONG RAW can be used to store graphics, sound, documents, or arrays of binary data
ROWID and UROWID Data types
 Oracle uses a ROWID data type to store the address (ROWID) of every row in the database
 Physical ROWID, LOGICAL ROWID (will be explained later)
LOB Data types
 They enable you to store large blocks of unstructured data (such as text, graphic images, video
clips, and sound waveforms) up to 4 gigabytes in size
 Oracle Corporation recommends that you always use LOB data types over LONG data types
1. BLOB – stores unstructured binary data in the database
2. CLOB and NCLOB – stores character data in the database
3. BFILE
a. Stores unstructured binary data in operating-system files outside the database
b. BFILE column or attribute stores a file locator that points to an external file containing
the data
c. FILEs are read-only; you cannot modify them












15

There are various tools available in the market which can be used at the client machine side to connect
to the Oracle Database Serevr and perform Database operation.
Few of such tools are TOAD Sequel Developer.
Oracle also offers you the tool by the name SQL PLUS which is the character made tool.
While you want connect from client machine to the Database server you need to provide the Authorized
USER ID and PASSWORD along with the connect string (Host String).
This Hoststring is mapped name which can be found in TNS NAMES.ORA file on the client machine.
This Hoststring is mapped to the IP ADDRESS and PORT NUMBER of the machine where Database server
is mounted / located.
How to connect Database : Connect xxxxx (User Name) / xxxxx (Password)
How to Disconnect Database: Disconnect;
1. CREATE Table Syntax:
we can define in Table 1 (Min) to 1000 (Max) columns.




Impact of Create Table:
• Oracle allocates data segment to store the data of this table.
• Information of this table is stored into data dictionary.
Recursive SQL’s:
• These are the statements fired by Oracle (internally) in response to the statements issued by
user.
• They are fired to update the information/data stored in the data dictionary tables
22-May-2011
Table Name
Datatype
Length
Column Name
Both ways we can create Table as
shown in above & below Figures
16

2. INSERT VALUES Syntax:



or




or

In Sequel plus last sequel statements is stored in the Buffer. If you want to modify the stored Database
in server.
We have 2 Options: 1. Sequel Command can be used.
2. Editor can be work to change that.
Note: If you are using ED in windows default editor is Notepad & Linux default editor is VI.
Using DEFAULT Clause:
• In Oracle by Default is NULL. If you want to change you assign DEFAULT clause.
• It can be used to provide the default values for the columns. In such cases, when you don’t
provide any values for these columns, instead of inserting NULL, ORACLE will insert values
provided with DEFAULT clause.
Use of & (Ampersand): It can be used in SQL*PLUS to accept the values on the
prompt.
3. SELECT Statement syntax:
SELECT <column_name(s)> | <*>||<expr>
FROM <table_name>
[WHERE <condition>]
[GROUP BY <expr>]
[HAVING <condition>]
[ORDER BY <expr>]

These ways we can Data Insert in Table
as shown in above & below Figures.
17



4. Comparison Operators:
Logical Operators: 1. AND
2. OR
3. NOT (This Operator always TRUE=FALSE & FALSE=TRUE)
Among these Logical Operators AND has get the higher precedence then OR, NOT.
So overwrite this presidency use brackets.
Operator Meaning
= Equal to
!=, <>, ^= Not Equal to
> Greater Than
< Less Than
>= Greater Than Equal to
<= Less Than Equal to
IN (<list of values>) Equal to one the values given in the list
BETWEEN <x> AND <y> Value is in the range of <x> and <y> including
values given in <x> and <y>
IS NULL and IS NOT NULL
LIKE ‘<pattern>’ % = Multi character replacement
_ Single character replacement
18

5. Using ORDER BY clause syntax:





19

Expression Example:




Oracle Instance : SGA + Background Process
Page setting command : set linesize XXXX; or set pagesize XXXX;









20


























As specified in the above diagram Data & Information stored in the SGA is shared among the all
sessions are connected (After Checking Privileges).
29-May-2011

ROLLBACK
SEGMENT
SGA (Shared / System) Global area
Database
Buffer Cache
Redolog
Buffer Cache
Shared Pool
PGA PGA PGA
Database Server
Session 1 Session 3 Session 2
Private/Program
Global area
Data files (Hard disk)
21

SGA is divided in to 3 Parts : 1. Database Buffer Cache
2. Redolog Buffer
3. Shared Pool
PGA: Whenever Session will be established Oracle allocates to the space at the server side to store
the session private information.


Database Engine: Every SQL statement goes to Database Engine for Execution.
Database Engine has 2 Parts 1) Optimizer
2) SQL statement Executor
1) Optimizer: Optimizer is responsible for generating the Execution plan.
2) SQL statement Executor: Execute the Sequel statements as per the plan generated by the Optimizer.
Shared Sequel Area:
• For every Unique Sequel statements Oracle generate the Execution plans Pars tree (a steps) which is
stored in the Shared pool in the form of Shared Sequel Area.
• For every sequel statement Oracle checks the Information store in the Data Dictionary which is
stored in the Data Dictionary cache inside the Shared Pool.
6. Following things happens internally when following Sequel (SQL) statements are executed?

Database Buffer Cache:
• It is newly Inserted data is stored into the Database Buffer Cache.
• This Inserted data available only that session that has inserted this data unless it is committed data
has not available to any other sessions.
Redolog Buffer:
• Redo entry generate by the insert statements is stored in the Redolog Buffer.
• When Session issues commit statement this redo entry saved in the Redolog Buffer and this new
inserted data stored in to Data Files (Hard Disk).
Note: Select Statement -----Oracle 1st checks into Database Buffer Cache. If require data is there if not then
its load that data from Datafiles (Harddisk) to the Database Buffer Cache.


22

7. UPDATE Ststement
UPDATE <table_name>
SET <column_name1> = <value1>
[, <column_name2> = <value2>
[WHERE <condition>]
DELETE FROM <name>
[WHERE <condition>]

• Oracle checks in the Database Buffer Cache for required Data. If it is not there it will load from
Datafiles (Harddisk).
• In case WHERE condition is not given and requires to manipulate the all records. It will lock that
record transfer the old values to the ROLLBACK SEGMENT and manipulates the new values in to the
Database Buffer Cache.
• Redo entry stored in to the Redolog Buffer.
• In case filter condition is given Oracle scans through each record. If the condition is satisfied then
locks that record and transverse to the old value ROLLBACK SEGMENT and update the record new
value in the Database Buffer Cache.
• Records to the locks for other sessions and only as read-only.
• For other sessions for updated records old values will be read from ROLLBACK SEGMENT.











8. ALTER statement syntax:

• Add one more columns to the existing table
• Modify the properties (Name, Data type, Length) of the existing columns
23

• enable, disable & drop integrity constraints [INTEGRITY CONSTRAINTS]
• enable, disable all database triggers applied on the table [PLSQL]
• change the storage clause and data block usage parameters [Oracle Internal Concepts]

ADD:
ALTER TABLE <name>
ADD (<Column_Name1> <Datatype> [(<Length>]
[, <Column_Name2> <Datatype> [(<Length>]]
.
.
.
)

Note: For exiting records, value for new column will be NULL











MODIFY:
ALTER TABLE <name>
MODIFY (<Column_Name1> <Datatype> [(<Length>]
[, <Column_Name2> <Datatype> [(<Length>]]
.
.
.
)

While modifying properties of the existing columns following should be kept in mind.

• You can Increase length whenever you want
24

• To decrease the length either column must be empty or The length you specified is not less than the
length of the actual value stored in that column.
• Datatype of the column change if data is empty.
• If column contains values then Datatype cannot be changed (Exception: Char to Varchar2 or
varchar2 to Char)














RENAME:
ALTER TABLE <name>
RENAME COLUMN <source name> TO <target name>








25

Note: After 9.I version only it will work ALTER COLUMN RENAME;

9. DROP Table Statement:

Syntax: DROP TABLE POLLACK;
Effects of Dropping Table:
• All records will be Deleted and Data segment will be released (freed)
• All relevant information will be removed from the Data Dictionary.
• Integrity constraints, Indexes and Database Triggers will be dropped along with the table.
• View, Synonyms, Stored Procedures, Stored Functions and packages will remain but it will be in
Invalid.

10. TRUNCATE Table Statement:

Syntax: TRUNCATE TABLE POLLACK;
The following are the differences between TRUNCATE and DELETE
11. RENAME Table Statement:
Syntax: RENAME POLLACK TO JADEJA;
S.No DELETE TRUNCATE
1 It is a DML statement It is a DDL statement
2 You can DELET specific record(s) using WHERE
clause
Can't use WHERE clause
3 Oracle maintains REDO entries Oracle doesn't maintain REDO entries
4 Deleted records can be recovered (using ROLLBACK) Truncated records cannot be recovered (using
ROLLBACK)
5 Fires Database Triggers Doesn’t fire Database Triggers
6 Can be used to DELETE the records from Parent and
clustered table
Cannot be used to DELETE the records from
Parent and clustered table
7 It is slower than TRUNCATE It is faster than DELETE
26

12. Transaction control Statement:

COMMIT:
• It is used to save the changes made by the given Transactions.
• All DDL, System control, Session control, DCL statements have implicit commit.

ROLLBACK:
• It is used to cancel the changes made by the Transactions.
SAVEPOINT:
• It is used to mark the portion of transaction by using unique name so that rolling back till that portion of
transaction is possible.
• ROLLBACK to statement can be used to ROLLBACK portions of transaction to specific SAVEPOINT.
• When you rollback to a particular SAVEPOINT, the save points THAT are applied after that will be
removed.
• When you use ROLLBACK or COMMIT, all the SAVEPOINTs applied in that transactions are removed.
• Oracle recommends you to use unique name for the save points in a given transaction.
















• Example:
SAVEPOINT A;
INSERT INTO
emp (empno, ename, sal, deptno)
VALUES (1007,’SACHIN’, 7500, 10);
SELECT * FROM emp;
SAVEPOINT B;
UPDATE emp SET SAL = SAL+1000;
SELECT * FROM emp;
DELETE FROM emp WHERE job=’CLERK’;
SELECT * FROM emp;
DELETE FROM emp;
SELECT * FROM emp;
ROLLBACK TO B;
SELECT * FROM emp;
ROLLBACK;
SELECT * FROM emp;

27

13. SET Transaction Statement:

Syntax: SET TRANSACTION READ ONLY;
• Once you set the transaction to READ ONLY you can issue only select statements.
• To come out of READ ONLY mode you have to issue COMMIT/ROLLBACK statement.
• All these select statement will read the data as of the point when the transaction was set read only.
• All the changes made and committed by other session will not be visible to the select statements issued
by you.




















28

Sr. No. Term Explanation
1 BPS Bits per Second
2 CPS characters per second
3 DBMS Database Management System
4 DOS Disk Operating System
5 DPI Dot per Inch
6 Ethernet IEEE 802.3 Standard LAN protocol
7 GB Gigabyte
8 Hz Hertz (cycles per second)
10 ISO International Standards Organization
11 KB kilobyte
12 KVA Kilovolt ampere
13 LAN Local area network
14 LPI Lines per inch
15 LPM Lines per minute
16 MB Megabyte
17 MTBF Mean time between failures
18 NIC Network interface card
19 NOS Network operating system
20 ODBC Open Database Connectivity
21 OLE Object Linking and Embedding
22 OS Operating system
23 PCL Printer Command Language
24 PPM Pages per minute
25 PS PostScript -- Adobe page description language
26 RAID Redundant array of inexpensive disks
27 RAM Random access memory
28 RISC Reduced Instruction-set computer
29 SCSI Small Computer system Interface
30 SNMP Simple Network management Protocol
31 SQL Structure Query language
32 TB Terabyte
33 TCP/IP Transmission Control Protocol/Internet Protocol
34 V Volt
35 WLAN Wireless LAN
36 GEC Groundwater Estimation Committee.
37 DC Data Center
38 DR Disaster Recovery
39 CGWB Central Ground Water Board
40 GEMS Groundwater Estimation Management System.






29

SQL Functions
Functions are a very powerful feature of SQL and can be used to do the following:
• Perform calculations on data
• Modify individual data items
• Manipulate output for groups of rows
• Format dates and numbers for display
• Convert values between data types

SQL functions sometimes take arguments and always return a value.



There are two distinct types of functions:
• Single-row functions
• Multi-row functions/Group Functions/Aggregate Functions

30


Single-Row Functions
Single-row functions are used to manipulate data items. They accept one or more arguments and
return one value for each row.
An argument can be one of the following:
• User-supplied constant
• Variable value
• Column name
• Expression

Syntax


function_name [(arg1, arg2,...)]

function_name is the name of the function.
arg1, arg2 is any argument to be used by the function. This can
be represented by a column name or expression.
31



• Character
• Number
• Date
• Conversion
• List Functions/General Functions

Character Functions and Operators

Single-row character functions accept character data as input and can return both
character or Numeric values. Based on their return type they are further classified
as.
 Character Functions Returning Character Values
 Character Functions Returning Number Values

Operator:
1) || (Concatenation Operator) - It is used to combine two more strings
together
32


 SELECT ename || ' Is working as '||job FROM emp

Character Functions Returning Character Values : The character functions
that return character values are:
 CHR

CHR returns char for the given ASCCI value
Examples

SELECT CHR(67)||CHR(65)||CHR(84) "Dog" FROM
DUAL;

Dog
---
CAT


 CONCAT



CONCAT returns char1 concatenated with char2. This function is equivalent to the
concatenation operator (||).
Examples

SELECT CONCAT(„Sachin‟, „Tendulkar ') as “Name”
FROM dual;

Name
SachinTendulkar
33

 INITCAP



INITCAP returns char, with the first letter of each word in uppercase, all other
letters in lowercase. Words are delimited by white space or characters that are not
alphanumeric.
Examples

SELECT INITCAP(„the tiger‟) "Capitals" FROM
DUAL;

Capitals
---------
The Tiger


 LOWER



LOWER returns char, with all letters lowercase.
Examples

SELECT LOWER('MR. SACHIN TENDULKAR')
"Lowercase"
FROM DUAL;

Lowercase
--------------------
mr. sachin tendulkar

34

 UPPER



UPPER returns the given char argument in upper case
Examples

SELECT „sachin tendulkar‟ as "Uppercase"
FROM dual;

Uppercase
----------------
SACHIN TENDULKAR

 LPAD

LPAD (<expr>,<n>, [,<char>])
LPAD returns the given expr, left-padded to length n with the sequence of
characters in <char>.
The argument n must be a NUMBER integer or a value that can be implicitly
converted to a NUMBER integer.
If you do not specify <char>, then the default is a blank space.
If expr is longer than n, then this function returns the portion of expr that fits in n.
The argument n is the total length of the return value.
Examples

SELECT LPAD(„SACHIN‟,15,'*') "LPAD example"
FROM DUAL;

LPAD example
---------------
35

*********SACHIN
 RPAD
RPAD (<expr>,<n>, [,<char>])

Opposite to LPAD
Examples

SELECT last_name, RPAD(last_name,10, '*')
"Name"
FROM employees
WHERE department_id = 80
ORDER BY last_name;

LAST_NAME Name
------------------------- ----------
Abel Abel******
Ande Ande******
Banda Banda*****
Bates Bates*****


 LTRIM
LTRIM(<expr>[,<char>)

1. It removes the given char from the left side of the given expr (till it finds another letter).
2. If char is not given then it removes blank spaces
Examples

SELECT first_name, LTRIM(first_name, 'V')
"Name"
FROM employees;

FIRST_NAME Name
36

-------------------- ---------------
Sachin Tendulkar Sachin Tendulkar
Saurav Ganguly Saurav Ganguly
Rahul Dravid Rahul Dravid
M S Dhoni M S Dhoni
Virendra Sehwag irendra Sehwag
Zaheer Khan Zaheer Khan
Anil Kumble Anil Kumble
VVS Laxman S Laxman


 RTRIM
RTRIM (<expr>[,<char>)

Opposite to LTRIM
Examples

SELECT RTRIM('Sachin Tendulkar**********','*')
"RTRIM example" FROM DUAL;

RTRIM exam
----------
Sachin Tendulkar





37

 TRIM



TRIM enables you to trim leading or trailing characters (or both) from a character
string.
 If you specify LEADING, then Oracle removes characters from left side
(works like LTRIM)
 If you specify TRAILING, then Oracle removes characters from right side
(works like RTRIM)
 If you specify BOTH or none of the three, then Oracle removes leading and
trailing characters equal to trim_character.
 If you do not specify trim_character, then the default value is a blank space.
 If you specify only trim_source, then Oracle removes leading and trailing
blank spaces.
 The function returns a value with datatype VARCHAR2. The maximum length
of the value is the length of trim_source.
 If either trim_source or trim_character is null, then the TRIM function
returns null.
Examples

SELECT First_Name,TRIM(LEADING „V‟ FROM
FIRST_NAME) as “Name”
FROM employees.

FIRST_NAME Name
-------------------- ---------------
Sachin Tendulkar Sachin Tendulkar
Saurav Ganguly Saurav Ganguly
Rahul Dravid Rahul Dravid
M S Dhoni M S Dhoni
Virendra Sehwag irendra Sehwag
Zaheer Khan Zaheer Khan
38

Anil Kumble Anil Kumble
VVS Laxman S Laxman





 REPLACE
REPLACE (<expr>, <search_string> [,<replacement_string>])

1. It searches for the given search_string into the given expr, replaces those
occurrences with the replacement_string and then returns that expression
2. The search_string and replacement_string may vary in the length
3. If replacement_string is not given then all occurrences of search_string are
removed
Examples

SELECT REPLACE('JACK and JUE','J','BL')
"Changes"
FROM DUAL;

Changes
--------------
BLACK and BLUE


 TRANSLATE
TRANSLATE (<expr>, <from>, <to>)

1. TRANSLATE returns the given expr, with all occurrences of from character to be replaced by its
corresponding character in to.
2. from and to length must match, if not then –
a. If from has more chars than to THEN they are removed
39

b. If to has more chars than from then they are ignored
Examples

SELECT TRANSLATE(„SACHIN TENDULKAR‟, 'ABC',
'XYZ') as “Translate”FROM DUAL;

Translate
--------------------
SXZHIN TENDULKXR

 SUBSTR
SUBSTR (<expr>,<m>[,<n>])

The SUBSTR function returns a portion of the given expr, starting at mth location
and n characters long.
 N is optional and in absence of the same, it returns entire string of given
expr starting at mth location
 If M is negative then it will start from the end of the given expr
 N can not be negative
Examples

SELECT SUBSTR('ABCDEFG',3,4) "Substring"
FROM DUAL;

Substring
---------
CDEF

SELECT SUBSTR('ABCDEFG',-5,4) "Substring"
FROM DUAL;

Substring
---------
CDEF
40

Character Functions Returning Number Values
Character functions that return number values can take as their argument any
character datatype.
The character functions that return number values are:
 ASCII


ASCII returns the ASCII value of the given character
If string is passed then it returns the ASCII value of the 1st character of that
string
Examples

SELECT ASCII(„L‟) as “VALUE” FROM dual;

VALUE
-----
76





 INSTR
INSTR(<expr>, <search>[,<m>[,<n>]] )

1. It returns the position of the search_string when found in to the given expr
2. Default values of M and N are 1
3. M stands for the search location. Value of N can be negative to start the search from end of
the expr
4. N stands for the occurrence
5. returns 0 if search_string is not found
Examples
41

SELECT INSTR('CORPORATE FLOOR','OR', 3, 2)
"Instring" FROM DUAL;

Instring
----------
14

SELECT INSTR('CORPORATE FLOOR','OR', -3, 2)
"Reversed Instring"
FROM DUAL;

Reversed Instring
-----------------
2



 LENGTH
length::=

The LENGTH functions return the length of char. The return value is of datatype
NUMBER. If char has datatype CHAR, then the length includes all trailing blanks. If
char is null, then this function returns null.
The following example uses the LENGTH function using a single-byte database character set:
Examples

SELECT LENGTH('SACHIN TENDULKAR') "Length in
characters"
FROM DUAL;

Length in characters
--------------------
16

42

Numeric Functions
Numeric functions accept numeric input and return numeric values

 ROUND
ROUND (<n>[,<m>)

1. ROUND returns n rounded to m places to the right of the decimal point
2. If you omit m, then n is rounded to 0 places
3. m can be negative to round off digits left of the decimal point
Examples

SELECT ROUND(15.193,1) "Round" FROM DUAL;

Round
----------
15.2



SELECT ROUND(15.193,-1) "Round" FROM DUAL;

Round
----------
20


SELECT ROUND(1.5), ROUND(2.5) FROM DUAL;

ROUND(1.5) ROUND(2.5)
---------- ----------
2 3




43

 TRUNC (number)
TRUNC(<n>[,<m>)

4. TRUNC returns n TRUNCATED to m places to the right of the decimal point
5. If you omit m, then n is TRUNCATED to 0 places
6. m can be negative to TRUNCATE digits left of the decimal point
Examples

SELECT TRUNC(15.79,1) "Truncate" FROM DUAL;

Truncate
----------
15.7

SELECT TRUNC(15.79,-1) "Truncate" FROM DUAL;

Truncate
----------
10




 CEIL



CEIL returns NEAREST integer greater than or equal to n.
Examples

SELECT CEIL(268651.8) as “Truncate” FROM dual;
44


Truncate
----------
268652

 FLOOR


FLOOR returns NEAREST integer less than or equal to n.
Examples

SELECT FLOOR(15.7) "Floor" FROM DUAL;

Floor
----------
15

 POWER
POWER (<n> ,<m>)

It returns n raised to power of m
Examples

SELECT POWER(3,2) "Raised" FROM DUAL;

Raised
----------
9



45

ABS
ABS (<n>)

It returns the absolute value n

Date Functions

Oracle Date Format

1. Oracle database stores dates in an internal numeric format,
representing the century, year, month, day, hours, minutes, and
seconds.
2. The default display and input format for any date is DD-MON-YY
or DD-MON-YYYY. Valid Oracle dates are between January 1,
4712 B.C. TO December 31, 9999 A.D.

SYSDATE
It returns the date and time information of the database server
Examples

SELECT SYSDATE as “TODAY”
FROM DUAL;

TODAY
---------
12-JUL-10


Note: Default date format is DD-MON-YY


46

Arithmetic with Dates
You can perform calculations using arithmetic operators such as + and -. You can
add and subtract number constants as well as dates. You can perform the
following operations:

Operation Result Description
date +
number Date
Adds a number of days to
a date
date -
number Date
Subtracts a number of days
from a date
date - date
Number
of days
Subtracts one date from
another
date +
number/24 Date
Adds a number of hours to
a date
Examples

SELECT first_name , hiredate , hiredate + 1 as
“NEXT DAY” , hiredate – 1 as “PREV DAY”
FROM dual;
FIRST_NAME HIREDATE NEXT DAY PREV DAY
---------- --------- --------- ---------
SACHIN 12-JUL-10 13-JUL-10 11-JUL-10

Note: SELECT ‟12-JAN-10‟ + 10 FROM dual;

The above example will throw an error. Because
it is a character string.



47

 ADD_MONTHS
ADD_MONTHS (<date> , <n>)

1. It adds given number of months to the given date
2. N can be negative to subtract the months
Examples

SELECT ADD_MONTHS(hire_date,1) "Next month"
FROM employees
WHERE last_name = 'SACHIN';

Next Month
-----------
07-JUL-89



 MONTHS_BETWEEN



1. MONTHS_BETWEEN returns number of months between dates date1 and
date2
2. If date1 is later than date2, then the result is positive. If date1 is earlier
than date2, then the result is negative
3. If date1 and date2 are either the same days of the month or both last days
of months, then the result is always an integer. Otherwise Oracle Database
calculates the fractional portion of the result based on a 31-day month and
considers the difference in time components date1 and date2.
Examples

SELECT MONTHS_BETWEEN('02-FEB-1995','01-JAN-
1995') "Months"
FROM DUAL;

48

Months
----------
1.03225806




 NEW_TIME



NEW_TIME returns the date and time in time zone timezone2 when date and time
in time zone timezone1 are date.
The arguments timezone1 and timezone2 can be any of these text strings:
 AST|ADT: Atlantic Standard or Daylight Time
 BST|BDT: Bering Standard or Daylight Time
 CST|CDT: Central Standard or Daylight Time
 EST|EDT: Eastern Standard or Daylight Time
 GMT: Greenwich Mean Time
 HST|HDT: Alaska-Hawaii Standard Time or Daylight Time.
 MST|MDT: Mountain Standard or Daylight Time
 NST: Newfoundland Standard Time
 PST|PDT: Pacific Standard or Daylight Time
 YST|YDT: Yukon Standard or Daylight Time
The following example returns an Atlantic Standard time, given the Pacific
Standard time equivalent:
Examples

ALTER SESSION SET NLS_DATE_FORMAT =
'DD-MON-YYYY HH24:MI:SS';

SELECT NEW_TIME(TO_DATE(
'11-10-99 01:23:45', 'MM-DD-YY HH24:MI:SS'),
'AST', 'PST') "New Date and Time" FROM DUAL;

New Date and Time
49

--------------------
09-NOV-1999 21:23:45


SELECT TO_CHAR(NEW_TIME(SYSDATE,'EST','PST'),'DD-MON-YYYY
HH24:MI:SS') FROM
DUAL
/
 NEXT_DAY

NEXT_DAY (<date>, <day>)
It returns the date of the day when it occurs after the given date.
Examples

SELECT NEXT_DAY('21-AUG-2011','SUNDAY') "NEXT
DAY"
FROM DUAL;

NEXT DAY
-----------
28-AUG-2011


 LAST_DAY


LAST_DAY returns the date of the last day of the month of given date
Examples

SELECT SYSDATE,
LAST_DAY(SYSDATE) "Last",
LAST_DAY(SYSDATE) - SYSDATE "Days Left"
FROM DUAL;
50


SYSDATE Last Days Left
--------- --------- ----------
30-MAY-01 31-MAY-01 1



Assignments
1. Want to count how many 'A' are there in the name
'AAMIR KHAN'
2. Find out how many days are left in the current month




Conversion Functions
Conversion functions convert a value from one data type to another


51


Function Purpose
TO_CHAR(number|date,[fmt
])
Converts a number or date value to a
VARCHAR2 character string as per the
given fmt
TO_NUMBER(char,[fmt])
Converts a character string
containing digits to a number as per
the given fmt
TO_DATE(char,[fmt])
Converts a character string
representing a date to a date value
according to the fmt specified. If fmt is
omitted, the format is DD-MON-YY or
DD-MON-YYYY unless you have
changed it

Examples

SELECT employee_id, TO_CHAR(hire_date, ‟MM/YY‟)
Month_Hired
FROM employees
WHERE last_name = ‟Sachin‟;

EMPLOYEE_ID MONTH
--------------------- -----------
102 06/94

SELECT TO_CHAR(salary, ‟$99,999.00‟) SALARY
52

FROM employees
WHERE last_name = ‟Sachin‟;

SALARY
------------
$3,103.00


SELECT TO_DATE(
'15/01/1989',
'dd/mm/yyyy‟) AS “Value”
FROM DUAL;

Value
---------
15-JAN-89


SELECT TO_NUMBER(„$3,103.00‟, ‟$99,999.00‟)
“VALUE”
FROM dual;

Value
--------
3103





53





Element Description
SCC or CC Century; server prefixes B.C. date with -
Years in dates YYYY
or SYYYY Year; server prefixes B.C. date with -
YYY or YY or Y Last three, two, or one digits of year
Y,YYY Year with comma in this position
IYYY, IYY, IY, I
Four, three, two, or one digit year based on
the ISO standard
SYEAR or YEAR
Year spelled out; server prefixes B.C. date
with -
BC or AD B.C./.D. indicator
B.C. or A.D. B.C./A.D. indicator with periods
Q Quarter of year
MM Month: two-digit value
MONTH
Name of month padded with blanks to
length of nine characters
MON Name of month, three-letter abbreviation
RM Roman numeral month
WW or W Week of year or month
DDD or DD or D Day of year, month, or week
DAY
Name of day padded with blanks to a
length of nine characters
54

DY Name of day; three-letter abbreviation
J
Julian day; the number of days since 31
December 4713 B.C.
AM or PM Meridian indicator
A.M. or P.M. Meridian indicator with periods
HH or HH12 or HH24 Hour of day, or hour (1–12), or hour
MI Minute (0–59)
SS Second (0–59)
SSSSS Seconds past midnight (0–86399)
/ . , Punctuation is reproduced in the result
“of the” Quoted string is reproduced in the result
TH
Ordinal number (for example, DDTH for
4TH)
SP
Spelled-out number (for example, DDSP for
FOUR)
SPTH or THSP
Spelled-out ordinal numbers (for example,
DDSPTH for FOURTH)
9 Represents a number
0 Forces a zero to be displayed
$ Places a floating dollar sign
L Uses the floating local currency symbol
. Prints a decimal point
, Prints a thousand indicator
MI
Minus signs to right (negative values)
55

999999MI 1234-
PR
Parenthesize negative numbers 999999PR
<1234>
EEEE
Scientific notation (format must specify
four Es) 99.999EEEE 1.234E+03
V
Multiply by 10 n times (n = number of 9s
after V) 9999V99 123400
B Display zero values as blank, not 0





List Functions

 GREATEST


 GREATEST returns the greatest of the list of one or more expressions. Oracle
Database uses the first expr to determine the return type. If the first expr is
numeric, then Oracle determines the argument with the highest numeric
precedence, implicitly converts the remaining arguments to that datatype
before the comparison, and returns the value of that datatype. If the first
expr is not numeric, then each expr after the first is implicitly converted to
the datatype of the first expr before the comparison.

Examples
56


SELECT GREATEST ('HARRY', 'HARRIOT', 'HAROLD')
"Greatest" FROM DUAL;

Greatest
--------
HARRY


 LEAST


Purpose
LEAST returns the least of the list of exprs. All exprs after the first are implicitly
converted to the datatype of the first expr before the comparison


Examples

SELECT LEAST('HARRY','HARRIOT','HAROLD')
"LEAST"
FROM DUAL;

LEAST
------
HAROLD




57

 NVL



If expr1 is null, then NVL returns expr2. If expr1 is not null, then NVL returns
expr1.
Examples

SELECT last_name, NVL(TO_CHAR(commission_pct),
'Not Applicable')
"COMMISSION"
FROM employees;

LAST_NAME COMMISSION
------------------------- ---------------------
-------------------
Sachin Not Applicable
Saurav Not Applicable
Anil .1
Rahul .15
Gautam Not Applicable
Sehwag .25
Zaheer Not Applicable
Dhoni .2
Laxman Not Applicable

 SIGN

SIGN returns the sign of n.
For value of NUMBER type, the sign is:
 -1 if n<0
 0 if n=0
 1 if n>0
Examples
58

SELECT SIGN(2000-3000),SIGN(200-200),SIGN(20-
10) FROM DUAL
/


 DECODE
Syntax
DECODE(<expr>, <search>, <result>, <default>)
DECODE(<expr>, <search>, <result>,
<search>, <result>,
<search>, <result>,
<searchn>, <resultn>,
<default>)
DECODE compares expr to each search value one by one. If expr is equal to a
search, then Oracle returns the corresponding result. If no match is found, then
Oracle returns default. If default is omitted, then Oracle returns null.
DECODE can contain arithmetic operators, SQL functions but it can not contain
COMPARISON and LOGICAL operators
The maximum number of components in the DECODE function, including expr,
searches, results, and default, is 255.
Nested DECODE can be given inside Result and/or DEFAULT
One DECODE can have only one expr and default
Examples

SELECT first_name as “NAME”,location_id ,
DECODE (location_id, 1, 'Southlake',
2, 'San
Francisco',
3, 'New Jersey',
4, 'Seattle',
'Non domestic')
59

"LOCATION"
FROM employees;


NAME LOCATION_ID
LOCATION
------------------------- ------------- ---
-----------------
Sachin 4 Seattle
Saurav 3 New
Jersey
Anil 2 San
Francisco
Rahul 5 Non
Domestic
Gautam 1 Southlake
Sehwag 4 Seattle

.
SELECT ename, deptno,DECODE(deptno,10,'SALES',
20, 'MKTG',
30, 'HRD', 'OTHERS') dname from emp
/
select ename, deptno,DECODE(deptno,10,SAL+2000,
20, SAL+2500,
SAL+500) "Incr Sal" from emp
/


SELECT ename, deptno,DECODE(deptno,10,DECODE(UPPER(job),'MANAGER',sal+2000,
'CLERK',sal+1500,
sal+1000
),
60

20,DECODE(UPPER(job),'MANAGER',sal+2500,
sal+1200),
sal+700
) "Incr Sal" from emp
/

Assignment
CONDITION Result
sal > 5000 1500
sal <= 5000 and >=3000 1200
sal < 3000 and > 2000 700
else

UPDATE emp
SET sal = DECODE(SIGN(sal-5000),1,sal+1500,
DECODE(sign(sal-2999),1,sal+1200,
DECODE(sign(sal-2000),1,sal+700,
sal+500)))
/




61

Aggregate Functions/Group Functions
1. Aggregate functions return a single result based on groups of rows, rather
than on single row.
2. Oracle applies the aggregate functions to each group of rows and returns a
single result for each group. If you omit the GROUP BY clause, then Oracle
applies aggregate functions to all the rows stored in that column.
3. All aggregate functions except COUNT(*) ignore nulls
4. You can use the NVL function in the argument to an aggregate function to
substitute a value for a null.
5. COUNT never returns null, but returns either a number or zero.
6. For all the remaining aggregate functions, if the data set contains no rows,
or contains only rows with nulls, then the function returns null.

 AVG
AVG (<expr>)
AVG returns average value of expr.
Examples

SELECT AVG(salary) "Average" FROM employees;


Average
--------
6425


 SUM
SUM(<expr>)
SUM returns the sum of values of expr.
Examples

SELECT SUM(salary) "Total"
FROM employees;

Total
62

----------
691400
 MIN
MIN (<expr>)
MIN returns minimum value of expr.
Examples

SELECT MIN(hire_date) "Earliest" FROM
employees;

Earliest
---------
17-JUN-87


 MAX
MAX (<expr>)
MAX returns maximum value of expr.
Examples

SELECT MAX(salary) "Maximum" FROM employees;

Maximum
----------
24000


 COUNT
COUNT (* | <expr>)

1. COUNT returns the number of rows returned by the query.
63

2. If you specify expr, then COUNT returns the number of rows where expr is not
null.
3. If you specify the asterisk (*), then this function returns all rows, including
nulls.
4. COUNT never returns null.
Examples
SELECT COUNT(*) "Total" FROM employees;

Total
----------
107

SELECT COUNT(*) "Allstars" FROM employees
WHERE commission_pct > 0;

Allstars
---------
35

SELECT COUNT(commission_pct) "Count" FROM
employees;

Count
----------
35

SELECT COUNT(DISTINCT manager_id) "Managers"
FROM employees;

Managers
----------
18



SELECT COUNT(empno),COUNT(comm) FROM emp


64

DISTINCT Clause

1. Returns UNIQUE values of the given column(s)
2. Oracle (internally) uses GROUP BY clause to create groups of the values stored in the columns
specified in the DISTINCT clause
3. In earlier versions of Oracle (9i and earlier), ORACLE also uses ORDER BY clause

SELECT DISTINCT DEPTNO FROM EMP

SELECT DISTINCT DEPTNO,JOB FROM EMP


GROUP BY Clause

Sequence
<WHERE>
|
<ORDER BY> (implicit only up to ver 9i)
|
<GROUP BY>
|
<GROUP FUNCTIONS>
|
<DISTINCT> (Implicit)
|
<ORDER BY> (if specified explicitly)

65

1. It is used to create the groups of all duplicate values so that group function can return one
results for each group
2. Column specified in SELECT statement should be used in GROUP BY clause, but column used in
GROUP BY clause, can be skipped during SELECTion

SELECT deptno,SUM(sal) FROM emp GROUP BY deptno ORDER BY deptno

SELECT deptno,job, SUM(sal),COUNT(empno) FROM emp GROUP BY deptno, job ORDER BY deptno,job
/
SELECT deptno, SUM(sal), AVG(sal), COUNT(*) FROM emp WHERE job = 'CLERK' GROUP BY deptno
/
HAVING Clause
Sequence
<WHERE>
|
<ORDER BY> (implicit only up to ver 9i)
|
<GROUP BY>
|
<GROUP FUNCTIONS>
|
<HAVING>
|
<DISTINCT> (Implicit)
|
<ORDER BY> (if specified explicitly)
1. It is used to filter the groups (created by the GROUP BY c
lause), based on the given filter condition
66


SET OPERATORS
1) UNION
2) UNION ALL
3) MINUS
4) INTERSECT

SET Operators can best be understood by the following example:

Considering the Following Table Structure:

Table
Name
Table Details

T1

SQL> SELECT * FROM T1;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- ---------- --------- ---------- -------
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7839 KING PRESIDENT 17-NOV-81 5000 10
7934 MILLER CLERK 7782 23-JAN-82 1300 10
7369 SMITH CLERK 7902 17-DEC-80 800 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
T2




SQL> SELECT * FROM T2;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7369 SMITH CLERK 7902 17-DEC-80 800 20
67

7566 JONES MANAGER 7839 02-APR-81 2975 20
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7876 ADAMS CLERK 7788 23-MAY-87 1100 20
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7900 JAMES CLERK 7698 03-DEC-81 950 30

T3





SQL> SELECT * FROM T3;

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7900 JAMES CLERK 7698 03-DEC-81 950 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7369 SMITH CLERK 7902 17-DEC-80 800 20








68

# SET Operator SQL Query Result/Remarks
1
UNION
(T1 and T2)
SQL> SELECT
ENAME,DEPTNO
FROM T1 UNION
SELECT
ENAME,DEPTNO
FROM T2;
ENAME DEPTNO
---------- ----------
ADAMS 20
CLARK 10
FORD 20
JAMES 30
JONES 20
KING 10
MILLER 10
SCOTT 20
SMITH 20
Note: Union does not retrieve duplicate records.
2
UNION
(T2 and T3)
SQL> SELECT
ENAME,DEPTNO
FROM T2 UNION
SELECT
ENAME,DEPTNO
FROM T3;
ENAME DEPTNO
---------- ----------
ADAMS 20
ALLEN 30
BLAKE 30
CLARK 10
FORD 20
JAMES 30
JONES 20
MARTIN 30
SCOTT 20
SMITH 20
TURNER 30
WARD 30
69

Note: Union does not retrieve duplicate records.
3
UNION ALL SQL> SELECT
ENAME,DEPTNO
FROM T1 UNION ALL
SELECT
ENAME,DEPTNO
FROM T3;
ENAME DEPTNO
---------- ----------
CLARK 10
KING 10
MILLER 10
SMITH 20
JAMES 30
ALLEN 30
WARD 30
MARTIN 30
BLAKE 30
TURNER 30
JAMES 30

CLARK 10
SMITH 20
Note: ‘Union all’ retrieves all the records. It
retrieves duplicate records as well.
70

4
INTERSECT
(T1 and T2)
SQL> SELECT
ENAME,DEPTNO
FROM T1 INTERSECT
SELECT
ENAME,DEPTNO
FROM T2;
ENAME DEPTNO
---------- ----------
CLARK 10
JAMES 30
SMITH 20

Note: SET Operator ‘Intersect’ displays only the
common between the two/more tables.
5
MINUS
(T1 and T2)
SQL> SELECT
ENAME,DEPTNO
FROM T1 minus
SELECT
ENAME,DEPTNO
FROM T2;

(Expression 1 MINUS
Expression 2)
ENAME DEPTNO
---------- ----------
KING 10
MILLER 10
Note: Minus Operator returns the records of
Expression 1, which are not in Expression 2. It
ignores the common records between Expression 1
and Expression 2.
6
MINUS
(T2 and T1)
SQL> SELECT
ENAME,DEPTNO
FROM T2 minus
SELECT
ENAME,DEPTNO
FROM T1;
ENAME DEPTNO
---------- ----------
ADAMS 20
FORD 20
JONES 20
SCOTT 20
71

7
MINUS
(T3 and T1)
SQL> SELECT
ENAME,DEPTNO
FROM T3 minus
SELECT
ENAME,DEPTNO
FROM T1;
ENAME DEPTNO
---------- ----------
ALLEN 30
BLAKE 30
MARTIN 30
TURNER 30
WARD 30




























72

J OINS
A join is a query that combines rows from two or more tables, views, or materialized views.
 Oracle Database performs a join whenever multiple tables appear in the FROM clause of the
query.
 The select list of the query can select any columns from any of these tables.
 If any two of these tables have a column name in common, then you must qualify all references
to these columns throughout the query with table names to avoid ambiguity.
Join Conditions
 Most join queries contain at least one join condition, either in the FROM clause or in the
WHERE clause.
 The join condition compares two columns, each from a different table. To execute a join, Oracle
Database combines pairs of rows, each containing one row from each table, for which the join
condition evaluates to TRUE.
 The columns in the join conditions need not also appear in the select list.
 To execute a join of three or more tables, Oracle first joins two of the tables based on the join
conditions comparing their columns and then joins the result to another table based on join
conditions containing columns of the joined tables and the new table. Oracle continues this
process until all tables are joined into the result.
 wHERE clause that contains a join condition can also contain other conditions that refer to
columns of only one table. These conditions can further restrict the rows returned by the join
query.
 In the process of joins, oracle uses temporary segment to store the immediate result of the
query processing. It compares each record of one table with every record of other table and
merges those records if the conditions are satisfied. The results are stored in the temporary
segment.
73

Obtaining Data from Multiple Tables

Sometimes you need to use data from more than one table. In the example, the report displays data
from two separate tables.
• Employee IDs exist in the EMPLOYEES table.
• Department IDs exist in both the EMPLOYEES and DEPARTMENTS tables.
• Location IDs exist in the DEPARTMENTS table.
To produce the report, you need to link the EMPLOYEES and DEPARTMENTS tables and access data
from both of them.

Cartesian Products
• A Cartesian product is formed when:
– A join condition is omitted
– A join condition is invalid
– All rows in the first table are joined to all rows in the second table
• To avoid a Cartesian product, always include a valid join condition in a WHERE clause.
Generating a Cartesian Product

74




Types of Joins
• Equijoin
• Non-equijoin
• Outer join
• Self join


Joining Tables Using Oracle Syntax


SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column1 = table2.column2;

• Write the join condition in the WHERE clause.
75

• Prefix the column name with the table name when the same column name appears in more than
one table.

Guidelines
• When writing a SELECT statement that joins tables, precede the column name with the table
name for clarity and to enhance database access.
• If the same column name appears in more than one table, the column name must be prefixed
with the table name.
• To join n tables together, you need a minimum of n-1 join conditions. For example, to join
four tables, a minimum of three joins is required. This rule may not apply if your table has a
concatenated primary key, in which case more than one column is required to uniquely identify
each row.
Equi-Join

 An equijoin is a join with a join condition containing an equality operator.
 An equijoin combines rows that have equivalent values for the specified columns.
 Equijoins are also called simple joins or inner joins.
Example


SELECT last_name, job_id, departments.department_id, department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id;

LAST_NAME JOB_ID DEPARTMENT_ID
DEPARTMENT_NAME
------------------- ---------- ------------- ---------------
. . .
Sachin FI_ACCOUNT 100 Finance
Urman SA_MAN 80 Sales
Popp FI_ACCOUNT 100 Finance
Russell SA_MAN 80 Sales
Partners SA_MAN 80 Sales
Errazuriz SA_MAN 80 Sales
Cambrault SA_MAN 80 Sales
Zlotkey SA_MAN 80 Sales
. . .


76


Using Table Aliases
• Simplify queries by using table aliases.
• Improve performance by using table prefixes.
Example


SELECT e.employee_id, e.last_name, e.department_id,
d.department_id, d.location_id
FROM employees e , departments d
WHERE e.department_id = d.department_id;

Guidelines
• Table aliases can be up to 30 characters in length, but shorter is better.
• If a table alias is used for a particular table name in the FROM clause, then that table alias must be
substituted for the table name throughout the SELECT statement.
• Table aliases should be meaningful.
• The table alias is valid only for the current SELECT statement.
Joining More than Two Tables


77


• To join n tables together, you need a minimum of n-1 join conditions. For example, to join three
tables, a minimum of two joins is required.

Example


SELECT e.last_name, d.department_name, l.city
FROM employees e, departments d, locations l
WHERE e.department_id = d.department_id
AND d.location_id = l.location_id;



SELECT empno,ename,sal,dname,loc
FROM dept,emp
WHERE dept.deptno = emp.deptno
/
SELECT empno,ename,sal,dept.deptno,dname,loc
FROM dept,emp
WHERE dept.deptno = emp.deptno
/
SELECT empno,ename,sal,d.deptno,dname,loc
FROM dept d,emp e
WHERE d.deptno = e.deptno
/

78

Non-Equijoins

A non-equijoin is a join condition containing OPERATOR other than an equality operator.
The relationship is obtained using an operator other than equals (=).
Example


SELECT e.last_name, e.salary, j.grade_level
FROM employees e, job_grades j
WHERE e.salary
BETWEEN j.lowest_sal AND j.highest_sal;





79





SELECT ename,sal,grade
FROM emp,salgrade
WHERE sal >= losal
AND sal <= hisal
/

Outer Joins
In case of equijoin / non equijoin the records that satisfy the conditions are retrieved. If a row
does not satisfy a join condition, the row will not appear in the query result.
The missing rows can be returned if an outer join operator is used in the join condition. The
operator is a plus sign enclosed in parentheses (+), and it is placed on the “side” of the join that is
deficient in information. This operator has the effect of creating one or more null rows, to which one or
more rows from the nondeficient table can be joined.
Outer Joins Syntax
• You use an outer join to also see rows that do not meet the join condition.
• The Outer join operator is the plus sign (+).

SELECT table1.column, table2.column
80

FROM table1, table2
WHERE table1.column(+) = table2.column;


SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column = table2.column(+);



Example







81









Outer Join Restrictions
• The outer join operator can appear on only one side of the expression—the side that has information
missing. It returns those rows from one table that has no direct match in the other table.
• A condition involving an outer join cannot use the IN operator
 In one single SELECT statement you can use the (+) operator in only one table and not on both
tables.

SELECT empno,ename,sal,d.deptno,dname,loc
FROM emp e, dept d
WHERE d.deptno = e.deptno (+)
/

Retrieve those departments which do not have any employees working in it
SELECT d.* FROM dept d, emp e

SELECT e.last_name, e.department_id, d.department_name
FROM employees e, departments d
WHERE e.department_id(+) = d.department_id ;

82

WHERE d.deptno = e.deptno (+)
AND empno IS NULL
/

SELECT ename,sal,grade
FROM emp,salgrade
WHERE sal >= losal (+)
AND sal <= hisal (+)
/



Self Joins
 A self join is a join of a table to itself.
 You need to specify the same table multiple times using different aliases in the FROM clause
 While you use one copy for selection, other copies must be used for filtration

Example


83


SELECT worker.last_name || ’ works for ’ || manager.last_name
FROM employees worker, employees manager
WHERE worker.manager_id = manager.employee_id ;







SELECT Y.empno, Y.ename, Y.sal FROM emp X, emp Y
WHERE Y.sal > X.sal
AND X.ename = 'MARTIN'
/

SELECT Y.empno, Y.ename, Y.sal FROM emp X, emp Y
WHERE Y.deptno = X.deptno
AND X.ename = 'FORD'
/

SELECT Y.empno, Y.ename, Y.sal FROM emp X, emp Y
84

WHERE Y.deptno = X.deptno
AND Y.ename != 'FORD'
AND X.ename = 'FORD'
/

SELECT z.empno, z.ename, z.sal FROM emp X, emp Y, emp z
WHERE z.deptno = x.deptno
AND X.ename = 'FORD'
AND z.sal > y.sal
AND y.ename = 'ADAMS'
/



SELECT z.empno, z.ename, z.sal,z.deptno,d.dname,d.loc
FROM emp X, emp Y, emp z,dept d
WHERE z.deptno = x.deptno
AND X.ename = 'FORD'
AND z.sal > y.sal
AND y.ename = 'ADAMS'
AND z.deptno = d.deptno
/




85

Sub-Queries
1. It is a query inside another query
2. A statement that contains sub-query is called as parent statement
3. It can be there in the FROM clause (called as inline view), WHERE clause (called as nested sub-
query)
4. There is no limit on number of Sub-queries in the FROM clause but WHERE clause can have 255
levels of sub-queries
5. Sub-Query is executed only once for the entire parent statement, irrespective of # of records
processed by the parent statement and they are executed prior to the execution of the parent
statement (exception co-related sub-query)
6. Sub-Query can be used in SELECT, INSERT, UPDATE, DELETE, WHERE, HAVING etc.

SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE ename = 'MARTIN')

Retrieve those employees who are working in the same department and on same job as ‘SMITH’

SELECT * FROM emp
WHERE (job,deptno) = (SELECT job,deptno FROM emp WHERE ename = 'SMITH')
/



Working in same dept as Martin and earning more than Adams
SELECT * FROM emp
WHERE sal > (SELECT sal FROM emp WHERE ename = 'ADAMS')
AND deptno = (SELECT deptno FROM emp WHERE ename = 'MARTIN')
/

Earning more than any of dept 20 employees
SELECT * FROM emp
86

WHERE sal >ANY (SELECT sal FROM emp WHERE deptno = 20)
/
SELECT * FROM emp
WHERE sal > (SELECT MIN(sal) FROM emp WHERE deptno = 20)
/

Earning more than ALL employees of dept 30
SELECT * FROM emp
WHERE sal >ALL (SELECT sal FROM emp WHERE deptno = 30)
/
SELECT * FROM emp
WHERE sal > (SELECT MAX(sal) FROM emp WHERE deptno = 30)
/


Ex of FROM clause query –

SELECT empno,ename,sal,e.deptno,sum_sal,total_emp,avg_sal
FROM emp e,
(SELECT deptno, SUM(sal) sum_sal, COUNT(empno) total_emp
,AVG(sal) avg_sal FROM emp GROUP BY deptno) d
WHERE e.deptno = d.deptno
/

SELECT empno,ename,sal,e.deptno,dname,loc,sum_sal,total_emp,avg_sal
FROM emp e,
87

(SELECT deptno, SUM(sal) sum_sal, COUNT(empno) total_emp
,AVG(sal) avg_sal FROM emp GROUP BY deptno) d,
dept d1
WHERE e.deptno = d.deptno
AND d1.deptno = e.deptno
/

UPDATE emp
SET (sal, deptno) = (SELECT sal,deptno FROM emp WHERE ename = 'SCOTT')
WHERE ename = 'BLAKE'
/

INSERT INTO emp (empno,ename,sal,job,deptno)
VALUES (1001, 'SACHIN', 10000, (SELECT job FROM emp WHERE ename = 'SCOTT'),
(SELECT deptno FROM emp WHERE ename = 'SMITH'))
/

Working on the same job as any of the employees of dept 20
SELECT * FROM emp
WHERE job IN (SELECT job FROM emp WHERE deptno = 20)
/

Select deptno, sum_sal & total no of employees where avg sal is greater than average sal of salesman

SELECT deptno, SUM(sal), COUNT(empno) FROM emp
GROUP BY deptno
88

HAVING AVG(sal) > (SELECT AVG(sal) FROM emp WHERE job = 'SALESMAN')
/




Display Average sal of deptno 20 as well

SELECT deptno, SUM(sal), COUNT(empno), avg_sal
FROM emp,
(SELECT AVG(sal) avg_sal FROM emp WHERE job = 'SALESMAN')
GROUP BY deptno, avg_sal
HAVING AVG(sal) > avg_sal













89

Co-Related Sub-Query
1. Oracle executes sub-query as co-related when Sub-query refers to the column of parent
statement table
2. In such cases, execution of sub-query is done in parallel to the execution of parent statement,
as well as sub-query is executed once for every record that is being processed in the parent
statement

SELECT empno,ename,sal,deptno from emp e
WHERE sal > (SELECT AVG(sal) FROM emp WHERE deptno = e.deptno)
/

EXISTS Operator – It evaluates the condition given in the parent statement to TRUE is sub-query
returns one or more records else FALSE

Retrieve those employees who have employees reporting to them –
SELECT * FROM emp x
WHERE EXISTS (SELECT * FROM emp WHERE mgr = x.empno)
/

Retrieve those employees who have NO employees reporting to them –
SELECT * FROM emp x
WHERE NOT EXISTS (SELECT * FROM emp WHERE mgr = x.empno)
/

Departments which have employees working –
SELECT * FROM dept d
WHERE EXISTS (SELECT 1 FROM emp WHERE deptno = d.deptno)
/
90


Creating new table from existing table

Syntax
CREATE TABLE <name> [(<column_names>)
AS
<SELECT statement>

To copy Structure and Data
CREATE TABLE temp AS SELECT * FROM emp;


To copy Structure and NO Data

CREATE TABLE TEMP AS SELECT * FROM EMP WHERE 1=2
/

To copy structure with different column names and data
CREATE TABLE temp (emp_no, emp_name, emp_sal, dno) AS
SELECT empno,ename,sal,deptno FROM emp








91

INTEGRITY CONSTRAINTS

Data Integrity:-
Data stored in the Database must be as per business rules. These Business rules guarantees are
that Authentic and valid data is stored into the Database.

They are 2 mechanisms that are used to implement the Data Integrity:
1) INTEGRITY CONSTRAINTS
2) DATABASE TRIGGERS

NOTE:-
CONSTRAINT means VALIDATION.
NORMALIZATION means Reduce the Data Redundancy.
CONSTRAINT has 2 attributes
1) CONSTRAINTS must be applied on the column of the TABLE.
2) Every CONSTRAINT must have the NAME and TYPE.

There are 5 types of Data Integrity Constraints.
1) NOT NULL
2) UNIQUE
3) PRIMARY KEY
4) FOREIGN KEY (REFERENCES-Referential Integrity Constraint)
5) CHECK


92

These constraints can be name uniquely and information of these constraints is stored in Data
Dictionary.
If you don’t give you the name to the constraints ORACLE will internally generate the name that
starts with sys underscore (SYS_).
NOTE: - ORACLE always checks for NOT NULL constraints first. Then TABLE LEVEL and COLUMN LEVEL.
DESC USER_CONSTRAINTS;

Can be used to retrieve the information about the constraints.

1. NOT NULL

a) It does not allow inserting NULL values into that column.
b) It can be only at column level.

CREATE TABLE my_emp
(
empno NUMBER (5) CONSTRAINT nn_myemp_empno NOT NULL,
ename VARCHAR2 (30)
);

Our own devised standard to provide the name is –<type>_<table_name>_<column_name>
SELECT * FROM USER_CONSTRAINTS;
SELECT constraint_name, constraint_type FROM user_constraints;


nn_myemp_empno

nn ===> constraint type
my_emp ===> table_name
empno ===> column_name
Example: 1
93

SELECT constraint_name, constraint_type
FROM user_constraints
WHERE table_name = ‘MY_EMP'
/
INSERT INTO my_emp VALUES (1001,'ABC');
INSERT INTO my_emp VALUES (NULL,'PQR');
INSERT INTO my_emp VALUES (1001,'ABC');
INSERT INTO my_emp (ename) VALUES ('XYZ');
2. UNIQUE

a) It does not allow duplicate values
b) Oracle internally creates an UNIQUE INDEX on that column by the same name as the name
on the constraint
c) It can be applied at table level as well as column level
d) It can be applied on two or more columns (composite UNQIE constraint)
e) Composite UNIQUE constraint MUST BE applied at table level
f) You can insert multiple NULLS in such columns


-- Column Level
CREATE TABLE my_emp
(
empno NUMBER (5) CONSTRAINT uk_myemp_empno UNIQUE,
ename VARCHAR2 (25)
);
Example: 1
94


SELECT constraint_name, constraint_type
FROM user_constraints
WHERE table_name = ‘MY_EMP';

SELECT index_name, index_type, uniqueness
FROM user_indexes
WHERE table_name = ‘MY_EMP';







-- Table Level

CREATE TABLE my_emp
(
empno NUMBER (5),
ename VARCHAR2 (25),
CONSTRAINT uk_myemp_empno UNIQUE (empno)
);
Example: 2
95

INSERT INTO my_emp VALUES (1001,'ABC');
INSERT INTO my_emp VALUES (NULL,'PQR');
INSERT INTO my_emp VALUES (1001,'ABC');
INSERT INTO my_emp (ename) VALUES ('XYZ');

-- Composite UNIQUE constraint
CREATE TABLE order_tran
(
ordno NUMBER (5),
ino NUMBER (5),
qty NUMBER (8),
CONSTRAINT cuk_ordertran_ordnoino UNIQUE (ordno, ino)
);
INSERT the following values and check which will work and which will not –
Sr. No Ordno Ino Qty
1 1001 5001 800
2 1001 5002 800
3 1001 5001 800
4 5001 1001 800
5 5001 1002 800
6 NULL NULL 800
7 5001 NULL 800
8 5001 NULL 800
Example: 3
96

9 NULL 5001 800
10 NULL 5001 800
11 NULL NULL 800

3. PRIMARY KEY

a) It is used to uniquely identify the records of the relational table
b) There can be only one primary key per table
c) Oracle implicitly does the following –
- Applies NOT NULL
- Creates UNIQUE INDEX on the primary key (column(s))
d) Oracle does not allow duplicate values as well as NULLs for PRIMARY KEY
e) It can be applied at table level as well as column level
f) It can be composite. Oracle does not allow NULLs in any of the columns participating in
composite PRIMARY KEY
g) Composite Primary key MUST BE applied at Table Level


-- Column Level

CREATE TABLE my_emp
(
empno NUMBER (5) CONSTRAINT pk_myemp_empno PRIMARY KEY,
ename VARCHAR2 (25)
);


Example: 1
97

-- Table Level

CREATE TABLE my_emp
(
empno NUMBER (5),
ename VARCHAR2 (25),
CONSTRAINT pk_myemp_empno PRIMARY KEY (empno)
);

-- Composite PRIMARY KEY constraint

CREATE TABLE order_tran
(
ordno NUMBER (5),
ino NUMBER (5),
qty NUMBER (8),
CONSTRAINT cuk_ordertran_ordino PRIMARY KEY (ordno, ino)
);
Try the following –

Sr. No Ordno Ino Qty
1 1001 5001 800
2 1001 5002 800
Example: 2
Example: 3
98

3 1001 5001 800
4 5001 1001 800
5 5001 1002 800
6 NULL NULL 800
7 5001 NULL 800
8 5001 NULL 800
9 NULL 5001 800
10 NULL 5001 800
11 NULL NULL 800


4. FOREIGN KEY [REFERENCES]

a) FOREINGN KEY is the column(s) that refers to the values of the PARENT KEY.
b) PARENT KEY should have either UNIQUE or PRIMARY KEY constraint.
c) Referential Integrity rules guarantees that this PARENT/CHILD relationship is preserved.
d) It can be applied at table level as well as column level.
e) FOREIGN KEY can be composite and should refer to composite parent key having same
number of columns and data type.
f) Table that contains parent key is called as parent table and the table that contain foreign
key is called as child table.
g) If foreign key refers to the parent key of the same table then it is called as "self referential
integrity".
h) Can insert NULLS.
i) You need to use CASCADE CONSTRAINTS option along with DROP TABLE to drop the parent
table. In this case, Oracle will DROP all foreign keys towards this parent table and then will
drop the parent table. Child Table structure and data will remain.
DROP TABLE <name> CASCADE CONSTRAINTS;
99


-- Column Level

CREATE TABLE my_dept
(
dname VARCHAR2 (15),
loc VARCHAR2 (25),
deptno NUMBER (5) CONSTRAINT pk_mydept_deptno
PRIMARY KEY
);

CREATE TABLE my_emp
(
empno NUMBER (10),
ename VARCHAR2 (25),
deptno NUMBER (5) CONSTRAINT fk_myemp_deptno
REFERENCES my_dept (deptno)
);
-- giving column name is optional. In absence of column name, by default FK will refer to Primary KEY
of that table.
-- Table Level


Example: 1
Example: 2
100

CREATE TABLE my_dept
(
dname VARCHAR2 (10),
dloc VARCHAR2 (25),
deptno NUMBER (5),
CONSTRAINT pk_mydept_deptno PRIMARY KEY (deptno)
);

CREATE TABLE my_emp
(
empno NUMBER (10),
ename VARCHAR2 (25),
deptno NUMBER (5),
CONSTRAINT fk_myemp_deptno FOREIGN KEY (deptno)
REFERENCES my_dept (deptno)
);


Statement Issued against Parent Table Issued against Child Table
INSERT Always OK
OK. Only if it matches with
Parent Key or it is NULL
UPDATE [RESTRICT]
OK only if parent key is not
referred by the FK
Same as above
DELETE [RESTRICT] Same as above Always OK
DELETE CASCADE Always OK Always OK

101


Note: If FK is defined using ON DELETE CASCADE then when you DELETE records from Parent Table, all
records from Child Table also will be deleted
--Self Referential Integrity

CREATE TABLE my_emp
(
empno NUMBER (5) PRIMARY KEY,
ename VARCHAR2 (25),
deptno NUMBER (2),
mgr NUMBER (5) CONSTRAINT fk_myemp_mgr
REFERENCES my_emp
);

CREATE TABLE my_emp
(
empno NUMBER (5) PRIMARY KEY,
ename VARCHAR2 (25),
deptno NUMBER (2),
mgr NUMBER (5) CONSTRAINT fk_myemp_mgr
REFERENCES my_emp,
CONSTRAINT fk_myemp_deptno FOREIGN KEY (deptno) REFERENCES my_emp
Example: 3
Example: 4
T
h
i
s

t
a
b
l
e

h
a
s

2

F
O
R
E
I
G
N

K
E
Y
s

102

);

Assume that you have empno and MGR starting with 1000 and then give following statement. Magic to
be researched by students –
UPDATE my_emp
SET empno=empno+4000,
mgr =mgr+4000
 Try out one example of composite FK……?
 Also find out if one column can have multiple Parent Keys i.e. can you have multiple FK
constraints one column…………?
5. CHECK

a) It allows you to check the conditions given in the CHECK constraint
b) If condition is evaluated to TRUE DML operation is allowed else Oracle will return an error
c) It can be defined at column level as well as table level
d) CHECK constraint can be Multi-Column but all these columns MUST belong to the same table and
it should be defined at table level
e) SQL functions can be used in CHECK constraint (except for SYSDATE and group functions)


-- Column Level

CREATE TABLE my_emp
(
empno NUMBER (5),
ename VARCHAR2 (25),
Example: 1
103

sal NUMBER (6) CONSTRAINT chk_myemp_sal CHECK
(sal>1000)
);
INSERT INTO my_emp VALUES (1001,'ABC', 5600);
INSERT INTO my_emp VALUES (1001,'ABC', 900);
INSERT INTO my_emp VALUES (1001,'ABC', NULL);
INSERT INTO my_emp VALUES (1001,'ABC', 0);









CREATE TABLE my_emp
(
empno NUMBER (5),
ename VARCHAR2 (25),
sal NUMBER (6) CONSTRAINT chk_myemp_sal CHECK (sal>1000),
comm NUMBER (6, 2),
CONSTRAINT chk_myemp_salcomm CHECK (sal>comm)
Example: 2
104

);
INSERT INTO my_emp VALUES (1001,'ABC', 1500, 600);
INSERT INTO my_emp VALUES (1001,'ABC', 900, 600);
INSERT INTO my_emp VALUES (1001,'ABC', 500,600);
INSERT INTO my_emp VALUES (1001,'ABC', NULL, 600);
INSERT INTO my_emp VALUES (1001,'ABC', NULL, NULL);

Adding Integrity constraints to existing tables

1. ALTER TABLE statement can be used to add the integrity constraints
2. ADD clause is used to add the table level constraints
3. MODIFY clause is used to add the column level constraints
4. Addition of constraint will result in an error if existing data is violating the same



Syntax

1. to add table level constraints

ALTER TABLE <table_name>
ADD (<constraint_details>
.
.
)

105

2. To add column level constraints

ALTER TABLE <table_name>
MODIFY (<column_name> <data_type> [(<length>)] < constraint_details>
.
.
)
Create the following table
CREATE TABLE temp
(
empno NUMBER (5),
ename VARCHAR2 (25),
sal NUMBER (5),
comm NUMBER (5, 2),
deptno NUMBER (2)
);
Add the following constraints to the above table
1. Empno should be primary key
2. ename should be in upper case
3. sal should not null
4. sal should be greater than comm.
5. deptno should be foreign key referring to the deptno of my_dept table

ALTER TABLE temp
ADD CONSTRAINT pk_temp_empno PRIMARY KEY (empno)
/
106


ALTER TABLE temp
ADD (CONSTRAINT chk_temp_ename CHECK (ename = UPPER (‘ename’)),
CONSTRAINT chk_temp_sal CHECK (sal > comm))
/
ALTER TABLE temp
MODIFY (sal NUMBER (5) CONSTRAINT nn_temp_sal NOT NULL)
/


ALTER TABLE temp
ADD (CONSTRAINT chk_temp_sal CHECK (sal > comm))
/
ALTER TABLE temp
ADD CONSTRAINT fk_temp_deptno FOREIGN KEY (deptno)
REFERENCES my_dept
/
Note: When you create a table from another table using CREATE TABLE …….AS….. Syntax, Oracle
will copy only NOT NULL constraint from the source table to the target table with system
generated name.

CREATE TABLE t1 AS SELECT * FROM temp;

 DESC temp
 DESC t1

107

SELECT constraint_name, constraint_type
FROM user_constraints
WHERE table_name = ‘T1’
/

How to add a new column having NOT NULL constraint
1. Add a column
2. update the values for the existing rows
3. Add NOT NULL constraint using ALTER TABLE….MODIFY……


Enable / Disable and Drop Integrity constraints



Syntax
ALTER TABLE <table_name> DISABLE|ENABLE|DROP CONSTRAINT <name>

1. You can disable the Integrity constraints. So that oracle does not check the constraints whenever
DML operations are performed.
2. Later on whenever you need you can Enable/Disable Integrity constraints.
3. At that time when you’re enabling the constraints all the data of that column will be check
against the constraint that we are enabling.
4. If any of the record is violating the Integrity constraint then constraint won’t be allow
enable/disable.
5. You may want to disable Integrity constraints in the following situations.
108


5.1 When you want to load major chunk of data and you want to save time of checking Integrity
constraints. You can disable the constraints and later on enable it when loading of data is
complete and monitoring is not required.
5.2 When you know that the data is loading is the transaction on performing is Inserting,
Updating or deleting the data which is violating the constraints. But you want allow the data
to get loaded or perform the transaction. Later on you want to correct the data and enable
the Integrity constraints.

TO DROP PRIMARY KEY –
ALTER TABLE <name> DROP PRIMARY KEY;
Note:
o You cannot drop the parent table unless you mention the CASCADE CONSTRAINTS clause.
o When you drop the parent table using this clause, Oracle will drop all the referential integrity
constraint towards this table and then drop the table

 DROP TABLE my_dept CASCADE CONSTRAINTS;







109

INDEX
















1. Index is a stores schema object
2. Indexes are used to improve the performance of SELECT statement.
3. When INDEXES are created Oracle allocates INDEX Segment to store the data of that INDEX.
4. INDEX segment stores value of an INDEX KEY along with the ROWID.
5. INDEX KEY can be composite.
6. There can be only one INDEX on one INDEX KEY.
7. INDEXES can be used only when INDEX KEY is used in filter conditions (WHERE Clause).
8. In such cases Oracle loads INDEX segment into Database Buffer Cache and also uses binary search
to filter the INDEX KEY. Once the INDEX KEY found it takes the ROWID of that matching INDEX key
and loads only those records from the data segment.
9. Thus INDEXES improve the performance by minimizing I/O (input/output) and reducing search
time.
10. Oracle recommends creating INDEXES only on those columns that are frequently used in filter
conditions. Because having too many INDEXES reduces the performance of DML operations. Since
INDEXES are maintained internally by oracle. Oracle has to update underlying INDEXES whenever
DML statements are performed on the table.
SGA (Shared / System) Global Area
Database
Buffer
Cache
Redolog
Buffer
Cache
Shared Pool
Session 1
Session 2 Session 3
Data Files (Hard Disk)
110

11. INDEX KEY can store duplicate values. If you don’t want INDEX KEY to store duplicate values then
you can create UNIQUE INDEXES.
12. Oracle corporation recommends you not to create UNIQUE INDEX instead apply UNIQUE
constraint.
13. Information about INDEXES which is stored in the Data dictionary can be retrieved from
USER_INDEXES.
SELECT index_name, index_type, uniqueness
FROM user_indexes
WHERE table_name=’EMP’;
SYNTAX :
CREATE INDEX <name>
ON <table name> (<column name(s)>)
Example:-
CREATE INDEX ind_empno ON emp (empno);

DROP INDEX <index name>;
Examples:-
DROP INDEX ind_empno;
CREATE UNIQUE INDEX ind_empno ON emp(empno);
CREATE INDEX ind_dnodname ON dept(deptno, dname);
CREATE INDEX ind_dno ON dept(deptno);
CREATE INDEX ind_dnamedno ON dept(deptno, dname);
Even if you give unique name for index, for the same columns which are already indexed. I t will
give error as “such column list already indexed”
CREATE INDEX ind_dnamedno ON dept(dname, deptno);
We can create index by changing the sequence/order of columns

111

Views
1. It is a (schema object) stored query/virtual table
2. It does not contain the data and hence there is no storage space consumed by the views
3. It derives the data from the base table
4. You can perform DML/SELECT operations on the views, which in turn are executed (internally)
on the base table of the view (by Oracle)
5. View does have it's own data structure, but you can not alter the same using ALTER statement
Syntax

CREATE VIEW <name> AS <SELECT statement>
Information of the views can be retrieved from user_views

SELECT text FROM USER_VIEWS WHERE view_name = '<view_name>';



VIEWS BASED ON expressions
CREATE VIEW v1 AS SELECT empno, ename, sal+2000 bonus, deptno FROM emp;

Note: Column alias MUST BE used for the expressions else Oracle will give an error

INSERT INTO v1 values (1005,'YUVRAJ',8000,30)
/
UPDATE v1 SET bonus = bonus + 4000
/
The above statements will result in an error because; bonus is a virtual column and not there in the
base table emp.


112

VIEWS BASED ON GROUP BY clause
CREATE VIEW v1 AS
SELECT deptno, SUM(sal) sum_sal, COUNT(empno) total_emp, MIN(sal) min_sal,
MAX(sal) max_sal, AVG(sal) avg_sal
FROM emp
GROUP BY deptno;

VIEWS BASED ON WHERE CLAUSE (Record filters)

CREATE VIEW v1 AS
SELECT *
FROM emp
WHERE deptno = 10
WITH CHECK OPTION
/
WITH CHECK OPTION – can be used if you want Oracle to check the given WHERE clause during INSERT
operation as well

READ ONLY VIEWS

Once you create the view as READ ONLY, you can not perform any operations other than SELECT

CREATE VIEW v1 AS
SELECT *
FROM emp
WITH READ ONLY
113


To find out which columns can be used in DML, you can use the following query –

SELECT column_name, updatable, insertable, deletable
FROM user_updatable_columns
WHERE table_name = 'V1'
/

VIEWS BASED ON JOINS
CREATE VIEW v1 AS
SELECT empno, ename, sal, d.deptno, dname, loc
FROM my_emp e, my_dept d
WHERE e.deptno = d.deptno
/
1. When views are having more than one base tables then you can perform the DML operations
only on key preserve tables (and their columns) and not on the NON-Key preserved table
2. In the process of join, if the table gets duplicate rows then that is NON key preserved table
3.

VIEWS BASED ON other views
CREATE VIEW v1 AS
SELECT *
FROM emp
/
CREATE VIEW v2 AS
SELECT empno, ename, sal, deptno
FROM v1
/
114

CREATE VIEW v3 AS
SELECT empno, deptno
FROM v2
/

In the above case, you perform DML, SELECT operation on any view, data will be modified/retrieved
from single base table

VIEWS BASED ON NON EXISTING OBJECTS

CREATE FORCE VIEW v1 AS
SELECT *
FROM temp
/
SQL> SHOW ERROR VIEW V1

1. When you create the view with FORCE option, ORACLE allows you to create a view but then
that view is in INVALID state
2. You can not perform any operations on INVALID objects

The following query can be used to find out the state of the object
SELECT status
FROM user_objects
WHERE object_name = 'V1'
/
3. These views can be brought to the VALID state only by creating the base tables and compiling
those views or by performing any operation on these views
4. To compile the views, you can use
a. ALTER VIEW <name> COMPILE
115

b. Perform any operation on that view so that ORACLE will internally compile the same

IMP NOTES
1. When you perform ALTER TABLE statement on the base table of the view, it will go in INVALID
state
2. Any new columns added after the view was created successfully will not be available when you
recompile the view
3. Changes made to the columns of the table that are SELECTed for the view will be available for
the view
4. When you DROP the table, view will go in INVALID state

USE of views
1. Query Simplicity – You can write the complex queries only once to create the view and then
after simple queries on the view. This way it helps to speed up the development process,
improves the quality and also saves the maintenance efforts
2. Security – You hide the base table from the user of the view. Also by creating the READ ONLY
views or views based on record filters, you can restrict the access to the data based as per the
users

























116



PL/SQL

1. PL/SQL is a programming language that combines both data manipulation and data processing
power.
2. It is used to store the business logic at database server side in the form of PL/SQL stored programs
units.
3. It is a block structured programming language.




Declaration Block






Execution Block
Notes:
All statements must be terminated by semicolon (;)
-- For single comment.
/* ___________________
_____________________ Multiple comment line
*/
4. It supports all SEQUEL data types as well as it has its own 3 data types.

a) BINARY_INTEGER
b) BOOLEAN
c) PLS_INTEGER






BEGIN
<Procedural statement>
<SQL statement>
.
.
[EXCEPTION
<Exception handler>]
END;

[DECLARE
<local declaration>]

09-Oct-2011
117

Notes:
BINARY_INTEGER just like NUMBER data type in SQL.
BOOLEAN like TRUE, FALSE and NULL.
Exception handling session is used to handle the runtime errors.
DBMS_OUTPUT.PUT_LINE (<string>)—It is debug print
SET SERVEROUTPUT ON—to get output from server.
: = For assigning value to Variable.
& (Ampersand) execute the before Compilation.

Role of PL/SQL

It is used to implement the business logic in the form of stored sub programs, packages and
database triggers.
PL/SQL code is used to process and manipulate the data as per the business rules.
PL/SQL code is not used to interact with the end users. End user interaction is handled by the
application program.
When stored in the database PL/SQL code is not executed implicitly by oracle unless you call or
execute it.
Business logic is stored at the database server side.



118

PL/SQL Engine has 2 parts
1. Compiler
2. Executor
Compiler compiles the entire PL/SQL block and generates the object code.
Compilation starts from the first line of the declaration session to the last line of the executable
session.
An executor executes the code as per the compiled object code.
Execution always starts from the first line of the executable session and will continue the
execution one by one.
During execution if it finds the SEQUEL statements it is send to the database engine for
execution.
And the control will wait for database engine response and executes the next line, if the
response is received with out any error.
If the response receives with an error then instead of executing the next line control will go to
the exception handler.

Programs (Anonymous or no named PL/SQL blocks)

-- This is my first program to learn basics of pl/sql
BEGIN
DBMS_OUTPUT.PUT_LINE ('Welcome to PLSQL');
END;
/
-- The below program teaches you to declare the variable, assign value
and display that value on screen

DECLARE
V_temp NUMBER (5);
BEGIN
119

v_temp:= 5000;
DBMS_OUTPUT.PUT_LINE ('Value of temp is: '||v_temp);
END;
-- It will give an error because v_temp is a constant and its value cannot be changed.

DECLARE
V_temp CONSTANT NUMBER (5);
BEGIN
V_temp:= 5000;
DBMS_OUTPUT.PUT_LINE ('Value of temp is: '||v_temp);
END;
/

-- Declaration of a constant v_temp must contain an initialization assignment. Expression v_temp
cannot be used as an assignment target because v_temp is a constant.
DECLARE
v_temp CONSTANT NUMBER (5) := 5000;
BEGIN
DBMS_OUTPUT.PUT_LINE (v_temp);
END;

-- The below program teaches you to declare the variable, accept the value on the prompt and
display that value on screen
DECLARE
v_temp NUMBER (5);
BEGIN
v_temp:= &temp;
DBMS_OUTPUT.PUT_LINE ('Value of Temp is: ' || v_temp);
120

END;

-- Write a program which will accept the emp name on the prompt
get the empno and salary of that employee from emp table,
and display the empno and sal on the screen
DECLARE
v_ename VARCHAR2 (25);
v_empno NUMBER (5);
v_sal NUMBER (5);
BEGIN
v_ename:= '&Ename';
-- Retrieving the employee details from emp table
SELECT empno, sal
INTO v_empno, v_sal
FROM emp
WHERE ename = v_ename;
-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE (v_empno || ' ' || v_sal);
END;
%TYPE

The above code may have to under go a change if there is change in the structure of the table and
either data type of length of the column is changed. That is because you are storing the values of those
columns into the PL/SQL variables and these variables should be of the same data type and length else
storing of the values may result in an error.
Use of %TYPE guarantees that the data type and length of such PL/SQL variables can be derived at run
time and based on data type and length of the columns
121

To decide the data type and length dynamically by oracle we use %TYPE



-- Write a program which will accept the emp name on the prompt get the empno and salary of that
employee from emp table and display the empno and sal on the screen

DECLARE
v_ename emp. ename %TYPE;
v_empno emp. empno %TYPE;
v_sal emp.sal %TYPE;
BEGIN
v_ename:= '&Ename';
-- Retrieving the employee details from emp table
SELECT empno, sal
INTO v_empno, v_sal
FROM emp
WHERE ename = v_ename;
-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE (v_empno || ' ' || v_sal);
END;

-- Write a program that will accept the emp name and increment amount on the prompt, increases
the salary by the given amount and displays the salary after increment

DECLARE
v_incr_amt NUMBER (5);
v_sal emp.sal %TYPE;
Example: 1
Example: 2
122

v_ename emp. ename %TYPE;
BEGIN
v_incr_amt:= &amount;
v_ename := '&ename';
UPDATE emp SET sal = sal + v_incr_amt
WHERE ename = v_ename;
SELECT sal INTO v_sal FROM emp
WHERE ename = v_ename;
-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE ('Salary after increment: ' || v_sal);
COMMIT;
END;
/
RETURNING Clause
1. This is an extension to the DML statement
2. This can be used to get the values of the record manipulated by the DML statement.
3. This eliminates the use of SELECT statement After UPDATE or INSERT and Before DELETE
statement
4. Helps to increase the performance of the code by reducing the context switch between
database engine and PL/SQL engine as well as reducing the need to process the same tables
two times i.e. ones for executing DML and again for SELECT statement.

DECLARE
v_incr_amt NUMBER (5);
v_sal emp.sal %TYPE;
v_ename emp. ename %TYPE;
BEGIN
v_incr_amt:= &amount;
v_ename := '&ename';
UPDATE emp SET sal = sal + v_incr_amt
WHERE ename = v_ename
RETURNING sal INTO v_sal;
-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE ('Salary after increment: ' || v_sal);
COMMIT;
END;





Example: 1 (UPDATE)
123

DECLARE
v_empno emp. empno %TYPE;
v_sal emp.sal %TYPE;
BEGIN
DELETE FROM emp
WHERE ename = '&ename'
RETURNING empno, sal
INTO v_empno, v_sal;
-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE
('deleted record values are: ' || v_empno || ' ' || v_sal);
END;



DECLARE
v_ename emp.ename %TYPE;
BEGIN
v_ename:='&ename';
INSERT INTO emp (empno, job, mgr, sal, comm)
VALUES (1111,'DEVELOPER', 7965, 1000, 20)
RETURNING ename
INTO v_ename;
DBMS_OUTPUT.PUT_LINE (v_ename);
COMMIT;
END;


Example: 2 (DELETE)
Example: 3 (INSERT)
124



%ROWTYPE










1) Variable of %ROWTYPE will be composite and will contain <n> (as many as columns there in the
table) number of member variables.
2) To access these member variables you have to precede the name of such variables before their
member name <rowtype_variable>.<member_variable>

-- Example to understand use of %ROWTYPE

DECLARE
v_row emp %ROWTYPE;
BEGIN
SELECT *
INTO v_row
FROM emp
WHERE empno = &empno;
V_ROW
empno ename

deptno job sal

Example: 1
06-Nov-2011
125

-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE ( v_row. Empno || ' '||
v_row. Ename || ' '||
v_row.sal || ' '||
v_row.job || ' '||
v_row. Deptno
);
END;
In case number of columns selected in the SELECT Statement and number of member variables therein
the ROWTYPE variable don’t match ORACLE will generate an error.
As well as the sequence of columns and member variables should match in terms of datatype and
length, if it does not then ORACLE will generate an error. To avoid above errors you need to
individually mention the member variables in INTO clause.
DECLARE
v_row emp %ROWTYPE;
BEGIN
SELECT empno, ename, sal, deptno
INTO v_row. empno, v_row. ename, v_row.sal, v_row. deptno
FROM emp
WHERE empno = &empno;
-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE ( v_row. empno || ' '||
v_row. ename || ' '||
v_row.sal || ' '||
v_row. Deptno
);
END;

Example: 2
126

User Defined data types
In Oracle there are two types of datatypes
1. Scalar
2. Composite
Variable of scalar type store a single value but variable of composite data type will contain the
members who will store the value of specific data types.
Note:
1. All SQL data types are scalar types
2. Variable of composite types contains other member variables which can contain values of
different data types.

RECORD Types

1. Users can create their own data types using RECORD Types.
2. These types can be used in a program to declare the variables etc.

-- Example to understand RECORD Types

DECLARE
TYPE emp_ty IS RECORD
(
empno emp. empno %TYPE,
ename emp. ename %TYPE,
sal emp.sal %TYPE,
deptno emp. deptno %TYPE
);
v_row emp_ty;
Example: 1
127

BEGIN
SELECT empno, ename, sal, deptno
INTO v_row
FROM emp
WHERE empno = &empno;
-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE ( v_row. empno || ' '||
v_row. ename || ' '||
v_row.sal || ' '||
v_row. deptno
);
END;


DECLARE
TYPE emp_ty IS RECORD
( empno emp.empno %TYPE,
ename emp.ename %TYPE,
sal emp.sal %TYPE,
deptno emp.deptno %TYPE,
comm emp.comm %type,
gross number (7,2) );
v_row emp_ty;
BEGIN
SELECT empno, ename, sal, deptno, comm, sal + NVL (comm,0)
INTO v_row
FROM emp
WHERE empno = &empno;
Example: 2
128

-- displaying those retrieved values
DBMS_OUTPUT.PUT_LINE ( v_row.empno || ' '||
v_row.ename || ' '||
v_row.sal || ' '||
v_row.deptno || ' '||
v_row.comm || ' '||
v_row.gross
);
END;
Nested RecordTypes

1. Variable of one record type is declared as member of another record type










-- Example to understand Nested RECORD Types
DECLARE
TYPE emp_ty IS RECORD
(
Empno emp. empno %TYPE,
V_ROW
dname loc emp_det
empno ename sal deptno
129

ename emp. ename %TYPE,
sal emp.sal %TYPE,
deptno emp. deptno %TYPE
);
TYPE dept_ty IS RECORD
(
dname dept.dname %TYPE,
loc dept.loc %TYPE,
emp_det emp_ty
);
v_row dept_ty;
BEGIN
SELECT dname, loc, empno, ename, sal, e.deptno
INTO v_row. dname, v_row.loc, v_row.emp_det.empno, v_row.emp_det.ename,
v_row.emp_det.sal, v_row.emp_det.deptno
FROM emp e, dept d
WHERE e.deptno = d.deptno
AND empno = &empno;
-- displaying those retrieved values

DBMS_OUTPUT.PUT_LINE ( v_row. dname || ' '||
v_row.loc || ' '||
v_row.emp_det.empno || ' '||
v_row.emp_det.ename || ' '||
v_row.emp_det.sal || ' '||
v_row.emp_det.deptno
);
END;
130

Conditional Structure (IF….ELSE…END IF)……….Syntax


IF <condition> THEN
<Pl/sql statements>
[ELSIF <condition> THEN
<Pl/sql statements>]
[ELSE
<Pl/sql statements>]
END IF;
-- Write a program that will accept empno on the prompt, retrieve the job of that given employee,
and increment the salary as per the below formula -
ANALYST -> 20%, MANAGER -> 21%, CLERK ->16%, SALESMAN ->18%, others -> 15%-- revised salary
DECLARE
v_job emp.job %TYPE;
v_empno emp.empno %TYPE: = &empno;
v_sal emp.sal %TYPE;
v_percent NUMBER (2);
BEGIN
SELECT job
INTO v_job
FROM emp
WHERE empno = v_empno;
IF v_job = 'ANALYST' THEN
v_percent:= 20;
ELSIF v_job = 'MANAGER' THEN
v_percent:= 21;
131

ELSIF v_job = 'CLERK' THEN
v_percent:= 16;
ELSIF v_job = 'SALESMAN' THEN
v_percent:= 18;
ELSE
v_percent:= 15;
END IF;
UPDATE emp
SET sal = sal + (sal*v_percent/100)
WHERE empno = v_empno
RETURNING sal
INTO v_sal;
DBMS_OUTPUT.PUT_LINE ('Record Updated. Salary is: ' || v_sal);
END;

LOOP Structure

1. It is used when you want to execute same set of statements again and again till the condition
satisfies
2. The following is the LOOP structure used in Oracle.

Loop …….. Syntax:
LOOP
<Pl/sql statements>
END LOOP;

DECLARE
Types of LOOPs
1. LOOP
2. WHILE LOOP
3. FOR LOOP
132

v_temp NUMBER (2):= 2;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Starting of loop');
LOOP
DBMS_OUTPUT.PUT_LINE (v_temp);
v_temp:= v_temp + 2;
IF v_temp > 20 THEN
EXIT;
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('End of Loop');
END;

You can use conditional EXIT instead of IF
DECLARE
v_temp NUMBER (2):= 2;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Starting of loop');
LOOP
DBMS_OUTPUT.PUT_LINE (v_temp);
v_temp:= v_temp + 2;
EXIT WHEN v_temp > 20;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('End of Loop');
END;
WHILE LOOP……………Syntax
WHILE <condition>
LOOP
<pl/sql statement>
END LOOP;
Example: 1
Example: 2
133


DECLARE
v_temp NUMBER (2):= 2;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Starting of loop');
WHILE v_temp <= 20
LOOP
DBMS_OUTPUT.PUT_LINE (v_temp);
v_temp:= v_temp + 2;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('End of Loop');
END;
FOR LOOP……………Syntax

FOR <expr> IN [REVERSE] <val1>...<val2>
LOOP
<pl/sql statements>
END LOOP;

1. <expr> is declared for the scope of FOR LOOP. Outside the body of the loop this expression can
not be accessed
2. <expr> is initialized by the value given in <val1> and will continue till it's value is less than equal
to the value given in <val2>
3. After each successive execution of the loop body value of <expr> is incremented by 1
BEGIN
FOR i IN 1...10
LOOP
DBMS_OUTPUT.PUT_LINE (i);
END LOOP;
DBMS_OUTPUT.PUT_LINE ('End of Loop');
END;
Note: You cannot assign value to the expression. It is READ ONLY for you.
Example: 1
134


BEGIN
FOR i IN 1...10
LOOP
DBMS_OUTPUT.PUT_LINE (i);
i: = i + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('End of Loop');
END;
Note: You can have same name for <expr> and variable declared in the PL/SQL block. In this case,
when you refer to that name inside FOR, local <expr> will take the higher precedence. To
override this, you can use the labels.
<<main>>
DECLARE
i NUMBER (3) := 100;
BEGIN
FOR i IN 1..10
LOOP
DBMS_OUTPUT.PUT_LINE (i);
main.i:= main.i + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('End of Loop: ' || i);
END;
Note: Sub.”I”will create an error as the “I” (variable) on the for loop can not be accessed out side the
loop.



135

<<main>>
DECLARE
I NUMBER: = 100;
BEGIN
<<sub>>
FOR I IN 1...10
LOOP
DBMS_OUTPUT.PUT_LINE (‘inside loop: '||main.I);
END LOOP;
DBMS_OUTPUT.PUT_LINE (‘outside loop: '|| sub.i);
END;
Use OF reverse
<expr> is initialized by the value given in <val2> and will continue till its value is greater than equal to
the value given in <val1>. Value is decreased by 1

BEGIN
FOR i IN REVERSE 1...5
LOOP
DBMS_OUTPUT.PUT_LINE (i);
END LOOP;
END;

LABELS and GOTO statemements
DECLARE
V_temp NUMBER (5):= 100;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Block');
<<abc>>
136

DBMS_OUTPUT.PUT_LINE ('In Side Label abc');
DBMS_OUTPUT.PUT_LINE ('Value of temp is: '||v_temp);
<<pqr>>
V_temp:= 500;
Goto xyz;
<<cab>>
DBMS_OUTPUT.PUT_LINE ('Value of temp in cab is: '||v_temp);
<<xyz>>
DBMS_OUTPUT.PUT_LINE ('In xyz value is: '||v_temp);
<<pac>>
DBMS_OUTPUT.PUT_LINE ('In pac value is: '||v_temp);
END;
Dry run the following program and find out the output –
BEGIN
DBMS_OUTPUT.PUT_LINE (‘before main loop');
<<mainloop>>
FOR i IN 1...5
LOOP
DBMS_OUTPUT.PUT_LINE (i);
DBMS_OUTPUT.PUT_LINE (‘before sub loop');
<<subloop>>
FOR k IN 10...15
LOOP
DBMS_OUTPUT.PUT_LINE (k);
EXIT mainloop WHEN i > 3;
END LOOP;
DBMS_OUTPUT.PUT_LINE (‘after sub loop');
END LOOP;
DBMS_OUTPUT.PUT_LINE (‘after main loop');
END;

Nested PL/SQL blocks

1. It is a block inside another block, In PL/SQL one block can reside in another block.
2. The block that is resides inside another block is called as nested, child or sub block.
137

3. The block that contains another block is called as parent or super block.
4. Nested block can any where between BEGIN and END

The following points are important when nested PL/SQL blocks are used
1) Declaration made inside parent block can be accessed by the statements issued in the nested
block.
2) Declaration made inside nested block can not be accessed by the statements given in the parent
block
3) If the parent block as well as the nested block has the declaration by the same name then the
statements issued in the nested block will access the local nested block declaration
(OR)
4) Local declarations will always have higher precedence then the global declaration. In such cases,
to access parent block declarations inside nested blocks labels can be used
NOTE: Labels can be used to over ride the precedence.
Variables declared in the parent block can be accessed by the nested block.











Variables declared in the nested block cannot be accessed by the parent block

DECLARE
v_temp NUMBER: = 100;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In parent Block: ' || v_temp);








DBMS_OUTPUT.PUT_LINE ('In parent again: ' || v_temp);
END;
BEGIN
v_temp:= 700;
DBMS_OUTPUT.PUT_LINE ('In nested block: ' || v_temp);
END;

138

DECLARE
v_temp NUMBER: = 100;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In parent Block: ' || v_temp);
DECLARE
v_cnt NUMBER: = 8000;
BEGIN
v_temp:= 700;
DBMS_OUTPUT.PUT_LINE ('In nested block: ' || v_cnt);
END;
DBMS_OUTPUT.PUT_LINE ('In parent again: ' || v_cnt);
END;
Local declaration will always have higher precedence than the global declaration
DECLARE
v_temp NUMBER: = 100;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In parent Block: ' || v_temp);
DECLARE
v_temp NUMBER: = 8000;
BEGIN
v_temp:= 700;
DBMS_OUTPUT.PUT_LINE ('In nested block: ' || v_temp);
END;
DBMS_OUTPUT.PUT_LINE ('In parent again: ' || v_temp);
END;
Note: Labels can be used to override the precedence –

139

<<mainblock>>
DECLARE
v_temp NUMBER: = 100;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In parent Block: ' || v_temp);
DECLARE
v_temp NUMBER: = 8000;
BEGIN
mainblock.v_temp:= 700;
DBMS_OUTPUT.PUT_LINE ('In nested block: ' || v_temp);
END;
DBMS_OUTPUT.PUT_LINE ('In parent again: ' || v_temp);
END;

PL/SQL Table (Index By Table)

1. PL/SQL table is a collection of multiple elements of same data type
2. Each element can be accessed using subscript or index number which is stored along with the
actual value
3. First you need to create INDEX by(PL/SQL table type) and then the variable of that is created
and this variable is called as PL/SQL table.
4. There is no limit on the number of elements PL/SQL table can contain.
DECLARE
TYPE tab_marks IS TABLE OF NUMBER (3) INDEX BY BINARY_INTEGER;
marks tab_marks;
BEGIN
FOR i IN 1...10
LOOP
140

marks (i):= i;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Printing the Values of PLSQL table ' ||marks.COUNT);
FOR i IN 1...marks.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE (marks (i));
END LOOP;
END;

Write a program to retrieve salary of all employees, store into PL/SQL table a then display on the
screen from that PL/SQL table

DECLARE
TYPE tab_sals IS TABLE OF emp.sal%TYPE INDEX BY BINARY_INTEGER;
v_sals tab_sals;
CURSOR cur_sal IS
SELECT sal FROM emp;
i NUMBER: = 1;
BEGIN
FOR rec_sal IN cur_sal
LOOP
v_sals (i):= rec_sal.sal;
i: = i + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Printing the saalry stored in PLSQL table ' ||v_sals.COUNT);
FOR k IN 1...v_sals.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE (v_sals (k));
END LOOP;
END;

DECLARE
TYPE emp_ty IS RECORD
(
empno NUMBER (5),
ename VARCHAR2 (25),
141

sal NUMBER (5)
);
TYPE emp_tab IS TABLE OF emp_ty INDEX BY BINARY_INTEGER;
v_emps emp_tab;
CURSOR c1 IS
SELECT empno, ename, sal FROM emp;
I NUMBER: = 1;
BEGIN
FOR r1 IN c1
LOOP
v_emps (i).empno:= r1.empno;
v_emps (i).ename:= r1.ename;
v_emps (i).sal := r1.sal;
i: = i+1;
END LOOP;
FOR k IN 1...v_emps.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE ( v_emps (k).empno||' '||
v_emps (k).ename||' '||
v_emps (k).sal
);
END LOOP;
END;





142

Cursors

1. It is a handle (pointer) to the work area that stores records (data)
2. It is required when there is a need to process more than one record
3. Using this handle, programmer can write a code to process records one by one
4. There are two types of Cursors
a. IMPLICIT
b. EXPLICIT

IMPLICIT – It is used by Oracle to process DML operations. It stores all those records that are processed
by the DML statement. If DML statement has not processed/manipulated any records then work area
will be empty

EXPLICIT
1. It has a SELECT statement associated with it
2. Records retrieved by the SELECT statement are stored in the work area pointed by the
explicit cursor
3. Using this handle/pointer programmer can process records one by one
4. There are two types of explicit cursors
a. STATIC – SELECT statement associated with this cursor is fix and does not change at
run time
b. REF – SELECT statement associated with this cursor can change at run time

STATIC Cursor

Syntax
CURSOR <name> [(<parameters>)] IS
<SELECT statement>

Example
-- This program is to learn the syntax and working a Cursor


143

DECLARE
CURSOR cur_emp IS
SELECT * FROM emp;
v_row emp%ROWTYPE;
BEGIN
OPEN cur_emp;
LOOP
FETCH cur_emp INTO v_row;
EXIT WHEN cur_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_row.empno || ' '||
v_row.ename || ' '||
v_row.sal || ' '||
v_row.deptno);
END LOOP;
CLOSE cur_emp;
END;
/

CURSOR Attributes

1. CURSOR has four attributes –
a. FOUND – Returns TRUE is FETCH is successful (explicit) or there are records in the work area
(Implicit)
b. NOTFOUND - Returns TRUE is FETCH is NOT successful (explicit) or there are NO records in the
work area (Implicit)
c. %ROWCOUNT – Gives current record number
d. %ISOPEN – Returns TRUE if CURSOR is opened else returns FALSE


Note: %ROWTYPE can be used for the cursor as well –

144

DECLARE
CURSOR cur_emp IS
SELECT empno,ename,sal,deptno FROM emp;
v_row cur_emp%ROWTYPE;
BEGIN
OPEN cur_emp;
LOOP
FETCH cur_emp INTO v_row;
EXIT WHEN cur_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(cur_emp%ROWCOUNT ||' '||
v_row.empno || ' '||
v_row.ename || ' '||
v_row.sal || ' '||
v_row.deptno);
END LOOP;
CLOSE cur_emp;
END;
/

CURSOR FOR Loop
-- This program is to learn the syntax and working a Cursor using FOR LOOP

DECLARE
CURSOR cur_emp IS
SELECT empno,ename,sal,deptno FROM emp;
BEGIN
FOR v_row IN cur_emp
LOOP
DBMS_OUTPUT.PUT_LINE(v_row.empno || ' '||
145

v_row.ename || ' '||
v_row.sal || ' '||
v_row.deptno);
END LOOP;
END;
1. In the above example, CURSOR cur_emp is opened only once at the start of the FOR LOOP
irrespective of total number of times loop body is executed
2. Cursor remains OPEN for the entire for LOOP
3. Oracle implicitly closes the cursor when control comes out of the LOOP

Note: You may skip the declaration of Cursor as follow –
BEGIN
FOR v_row IN (SELECT empno,ename,sal,deptno FROM emp)
LOOP
DBMS_OUTPUT.PUT_LINE(v_row.empno || ' '||
v_row.ename || ' '||
v_row.sal || ' '||
v_row.deptno);
END LOOP;
END;
/
Passing parameters to the Cursor
DECLARE
CURSOR cur_emp (prm_deptno emp.deptno%TYPE)
IS
SELECT empno,ename,sal,deptno
FROM emp WHERE deptno = prm_deptno;
BEGIN
FOR v_row IN cur_emp(10)
LOOP
146

DBMS_OUTPUT.PUT_LINE(v_row.empno || ' '||
v_row.ename || ' '||
v_row.sal || ' '||
v_row.deptno);
END LOOP;
END;
Accepting values on the prompt
DECLARE
CURSOR cur_emp (prm_deptno emp.deptno%TYPE)
IS
SELECT empno,ename,sal,deptno
FROM emp WHERE deptno = prm_deptno;
BEGIN
FOR v_row IN cur_emp(&deptno)
LOOP
DBMS_OUTPUT.PUT_LINE(v_row.empno || ' '||
v_row.ename || ' '||
v_row.sal || ' '||
v_row.deptno);
END LOOP;
END;

Question to students
Please write down the output of the following program assuming empno, ename and sal as below -

DECLARE
v_temp NUMBER(5) := 1000;
CURSOR cur_googly IS
SELECT empno,ename,sal,sal + v_temp bonus
147

FROM emp WHERE deptno=10;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before first loop value of temp is: ' || v_temp);

FOR v_googly IN cur_googly
LOOP
DBMS_OUTPUT.PUT_LINE(v_googly.empno || ' '||
v_googly.ename || ' '||
v_googly.sal || ' '||
v_googly.bonus);
v_temp := v_temp + 1000;
END LOOP;

DBMS_OUTPUT.PUT_LINE('After first loop value of temp is: ' || v_temp);

FOR v_googly IN cur_googly
LOOP
DBMS_OUTPUT.PUT_LINE(v_googly.empno || ' '||
v_googly.ename || ' '||
v_googly.sal || ' '||
v_googly.bonus);
v_temp := v_temp + 1000;
END LOOP;

DBMS_OUTPUT.PUT_LINE('After second loop value of temp is: ' || v_temp);

END;
/
148



EMPNO ENAME SAL BONUS (1st
loop)
BONUS (2nd
loop)
V_TEMP
1001 SACHIN 6000
1002 SAURAV 6500
1003 ANIL 3000



Example of multiple Cursors

Write a program to display following output –
1. Department details (deptno, dname, location) of one department
2. All employees working in that department (empno, ename, sal, job)

10 SALES MUMBAI
1001 SACHIN 5000 ANALYST
1003 SAURABH 6000 MANAGER
1008 ANIL 3000 CLERK
20 MKTG CHENNAI
1002 RAHUL 3000 SALEMAN
..
..
..

-- The following program is to understand tht one PL/SQL block can have multiple cursors
-- and values of the current record of one cursor can be passed as a paremeter to another
-- cursor
149


DECLARE
CURSOR cur_dept IS
SELECT * FROM dept;
CURSOR cur_emp (p_deptno emp.deptno%TYPE) IS
SELECT empno, ename, sal, job
FROM emp WHERE deptno = p_deptno;
BEGIN
FOR rec_dept IN cur_dept
LOOP
DBMS_OUTPUT.PUT_LINE(rec_dept.deptno ||' '||
rec_dept.dname ||' '||
rec_dept.loc);

FOR rec_emp IN cur_emp (rec_dept.deptno)
LOOP
DBMS_OUTPUT.PUT_LINE(rec_emp.empno ||' '||
rec_emp.ename ||' '||
rec_emp.sal ||' '||
rec_emp.job);
END LOOP;
DBMS_OUTPUT.PUT_LINE('***************End of department record**********');

END LOOP;
END;
/

Please modify the above program and display the text "No employees working in this department" in
case that department does not have any employees working in it
150


-- The following program is to understand tht one PL/SQL block can have multiple cursors
-- and values of the current record of one cursor can be passed as a paremeter to another
-- cursor

DECLARE
CURSOR cur_dept IS
SELECT * FROM dept;
CURSOR cur_emp (p_deptno emp.deptno%TYPE) IS
SELECT empno, ename, sal, job
FROM emp WHERE deptno = p_deptno;

v_flag BOOLEAN;
BEGIN
FOR rec_dept IN cur_dept
LOOP
DBMS_OUTPUT.PUT_LINE(rec_dept.deptno ||' '||
rec_dept.dname ||' '||
rec_dept.loc);

v_flag:=FALSE;
FOR rec_emp IN cur_emp (rec_dept.deptno)
LOOP
DBMS_OUTPUT.PUT_LINE(rec_emp.empno ||' '||
rec_emp.ename ||' '||
rec_emp.sal ||' '||
rec_emp.job);

v_flag:=TRUE;
151

END LOOP;

IF v_flag = FALSE THEN
DBMS_OUTPUT.PUT_LINE('NO DATA FOR '|| rec_dept.deptno);
END IF;

DBMS_OUTPUT.PUT_LINE('***************End of department record**********');

END LOOP;
END;

Please achieve the same output using %ROWCOUNT


Requirement
Write a PL/SQL block to increase the salary of all employees as follow –
1. MANAGER – 1500
2. ANALYST – 2000
3. CLERK – 1200
4. SALESMAN – 1000
5. PRESIDENT – 3000
6. OTHERS – 900

DECLARE
CURSOR cur_emp IS
SELECT empno, job
FROM emp;
v_incr_amt NUMBER(6);
BEGIN
FOR rec_emp IN cur_emp
LOOP
IF rec_emp.job = 'SALESMAN'
THEN
152

v_incr_amt := 1000;
ELSIF rec_emp.job = 'CLERK'
THEN
v_incr_amt := 1200;
ELSIF rec_emp.job = 'ANALYST'
THEN
v_incr_amt := 2000;
ELSIF rec_emp.job = 'MANAGER'
THEN
v_incr_amt := 1500;
ELSIF rec_emp.job = 'PRESIDENT'
THEN
v_incr_amt := 3000;
ELSE
v_incr_amt := 900;
END IF;

UPDATE emp
SET sal = sal + v_incr_amt
WHERE empno = rec_emp.empno;

END LOOP;

DBMS_OUTPUT.PUT_LINE ('Salary Increase Done');
END;
/

FOR UPDATE
1. It is an extension to the SELECT statement
2. It can be used to lock the records retrieved by the SELECT statement
3. These locks will be released only when you issue COMMIT or ROLLBACK
4. If SELECT statement is retrieving data from two or more tables, you have a choice of locking
data from specific table(s). To do so you need to use FOR UPDATE OF <column_name>. In this
case only that table(s) records will be locked whose <column_name> is mentioned.
EX. In the following case it will lock the records of DEPT table
SELECT empno,ename,sal,dname,loc
from emp e, dept d
where e.deptno=d.deptno
for update OF dname
153


5. NOWAIT can be specified if you don't want to wait to apply locks if some other session has
already locked those records.
CURRENT OF
1. It can be used along with the cursor name to manipulate the record that is currently being in
process in the cursor.
2. This clause can be used in WHERE clause of DML statement

DECLARE
CURSOR cur_emp IS
SELECT job
FROM emp FOR UPDATE;
v_incr_amt NUMBER(6);
BEGIN
FOR rec_emp IN cur_emp
LOOP
IF rec_emp.job = 'SALESMAN'
THEN
v_incr_amt := 1000;
ELSIF rec_emp.job = 'CLERK'
THEN
v_incr_amt := 1200;
ELSIF rec_emp.job = 'ANALYST'
THEN
v_incr_amt := 2000;
ELSIF rec_emp.job = 'MANAGER'
THEN
v_incr_amt := 1500;
ELSIF rec_emp.job = 'PRESIDENT'
THEN
v_incr_amt := 3000;
ELSE
v_incr_amt := 900;
END IF;

UPDATE emp
SET sal = sal + v_incr_amt
WHERE CURRENT OF cur_emp;

END LOOP;

DBMS_OUTPUT.PUT_LINE ('Salary Increase Done');
END;

154

IMP Notes
1. COMMIT/ROLLBACK can be used inside cursor LOOP but only FOR UPDATE is not used to
declare the cursor
2. If you try to perform an operation on closed cursor, oracle will return an error "Invalid Cursor"
3. If you try to open the cursor, which is already opened, oracle will return an error " Cursor
already open"

Implicit Cursors
BEGIN
UPDATE emp
SET sal = sal+1500
WHERE deptno = &deptno;

DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' Records are modified');
END;
BEGIN
UPDATE emp
SET sal = sal+1500
WHERE deptno = &deptno;

IF SQL%ROWCOUNT = 0 THEN
DBMS_OUTPUT.PUT_LINE ('Invalid deptno or no employees....please enter correct
deptno');
ELSE
DBMS_OUTPUT.PUT_LINE (SQL%ROWCOUNT || ' Records modified');
END IF;
END;



155

Cursor and Memory Management by Oracle

1. Cursor is a pointer to the private SQL area that is stored in PGA
2. Private SQL area stores the ROWID's of the records retrieved by the SELECT statements
associated with the cursor. These ROWIDs provide an access to the actual data
3. Actual data is stored in Database Buffer Cache and only one copy is shared among all connected
sessions









156

Exception Handling
What is an Exception?
1. It is an error thrown by Oracle while executing a program
2. This error is caused due to PL/SQL program not following the RULE or system defined limits
3. These exceptions can be handles by the programmer by using exception handler names and in
EXCEPTION section of a PL/SQL block

Pre-Defined Exceptions
PL/SQL declares predefined exceptions globally in package STANDARD, which defines the PL/SQL
environment. So, you need not declare them yourself.
Following are the pre-defined exceptions. Please note that exceptions marked with * are available with
Oracle 8 onwards and # with Oracle 8i onwards.
Exception Handler Name Oracle Error SQLCODE Value
ACCESS_INTO_NULL *
COLLECTION_IS_NULL *
CURSOR_ALREADY_OPEN
DUP_VAL_ON_INDEX
INVALID_CURSOR
INVALID_NUMBER
LOGIN_DENIED
NO_DATA_FOUND
NOT_LOGGED_ON
PROGRAM_ERROR
ROWTYPE_MISMATCH
SELF_IS_NULL #
STORAGE_ERROR
SUBSCRIPT_BEYOND_COUNT *
SUBSCRIPT_OUTSIDE_LIMIT *
SYS_INVALID_ROWID #
TIMEOUT_ON_RESOURCE
TOO_MANY_ROWS
VALUE_ERROR
ZERO_DIVIDE

ORA-06530
ORA-06531
ORA-06511
ORA-00001
ORA-01001
ORA-01722
ORA-01017
ORA-01403
ORA-01012
ORA-06501
ORA-06504
ORA-30625
ORA-06500
ORA-06533
ORA-06532
ORA-01410
ORA-00051
ORA-01422
ORA-06502
ORA-01476

-6530
-6531
-6511
-1
-1001
-1722
-1017
+100
-1012
-6501
-6504
-30625
-6500
-6533
-6532
-1410
-51
-1422
-6502
-1476





157


Brief descriptions of the predefined exceptions follow:
Exception Raised when ...
ACCESS_INTO_NULL *

Your program attempts to assign values to the attributes of an un
initialized (atomically null) object.
COLLECTION_IS_NULL *

Your program attempts to apply collection methods other than
EXISTS to an un initialized (atomically null) nested table or varray,
or the program attempts to assign values to the elements of an un
initialized nested table or varray.
CURSOR_ALREADY_OPEN

Your program attempts to open an already open cursor. A cursor
must be closed before it can be reopened.
A cursor FOR loop automatically opens the cursor to which it refers.
So, your program cannot open that cursor inside the loop.
DUP_VAL_ON_INDEX

Your program attempts to store duplicate values in a database
column that is constrained by a unique index.
INVALID_CURSOR

Your program attempts an illegal cursor operation such as closing an
unopened cursor.
INVALID_NUMBER

In a SQL statement, the conversion of a character string into a
number fails because the string does not represent a valid number.
(In procedural statements, VALUE_ERROR is raised.)
LOGIN_DENIED

Your program attempts to log on to Oracle with an invalid username
and/or password.
NO_DATA_FOUND

A SELECT INTO statement returns no rows, or your program
references a deleted element in a nested table or an uninitialized
element in an index-by table.
SQL aggregate functions such as AVG and SUM always return a
value or a null. So, a SELECT INTO statement that calls a aggregate
function will never raise NO_DATA_FOUND.
The FETCH statement is expected to return no rows eventually, so
when that happens, no exception is raised.
NOT_LOGGED_ON

Your program issues a database call without being connected to
Oracle.
PROGRAM_ERROR

PL/SQL has an internal problem.
158

ROWTYPE_MISMATCH

The host cursor variable and PL/SQL cursor variable involved in an
assignment have incompatible return types. For example, when an
open host cursor variable is passed to a stored subprogram, the return
types of the actual and formal parameters must be compatible.
SELF_IS_NULL #

Your program attempts to call a MEMBER method on a null
instance. That is, the built-in parameter SELF (which is always the
first parameter passed to a MEMBER method) is null.
STORAGE_ERROR

PL/SQL runs out of memory or memory has been corrupted.
SUBSCRIPT_BEYOND_COUNT *

Your program references a nested table or varray element using an
index number larger than the number of elements in the collection.
SUBSCRIPT_OUTSIDE_LIMIT *

Your program references a nested table or varray element using an
index number (-1 for example) that is outside the legal range.
SYS_INVALID_ROWID #

The conversion of a character string into a universal rowid fails
because the character string does not represent a valid rowid.
TIMEOUT_ON_RESOURCE

A time-out occurs while Oracle is waiting for a resource.
TOO_MANY_ROWS

A SELECT INTO statement returns more than one row.
VALUE_ERROR

An arithmetic, conversion, truncation, or size-constraint error occurs.
For example, when your program selects a column value into a
character variable, if the value is longer than the declared length of
the variable, PL/SQL aborts the assignment and raises
VALUE_ERROR.
In procedural statements, VALUE_ERROR is raised if the
conversion of a character string into a number fails. (In SQL
statements, INVALID_NUMBER is raised.)
ZERO_DIVIDE

Your program attempts to divide a number by zero.

DECLARE
v_sal NUMBER(4);
BEGIN
SELECT sal
INTO v_sal
159

FROM emp
WHERE ename = '&ename';

DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);

EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('Invalid employee...Please enter existing employee name');
END;
--------------------------------------------------------------------------------------------------------------------------------------------
DECLARE
v_sal NUMBER(4);
v_ename emp.ename%TYPE := '&ename';
BEGIN
SELECT sal
INTO v_sal
FROM emp
WHERE ename = v_ename;
DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('Invalid employee...Please enter existing employee name');
WHEN too_many_rows THEN
DECLARE
CURSOR cur_emp IS
SELECT empno,sal
FROM emp WHERE ename = v_ename;
BEGIN
FOR rec_emp IN cur_emp
160

LOOP
DBMS_OUTPUT.PUT_LINE (rec_emp.empno || ' ' || rec_emp.sal);
END LOOP;
END;
END;

OTHERS EXCEPTION HANDLER
1. This handler can be used for handling all run time errors that are not handled separately
2. This handler MUST BE in the end of exception handlers

DECLARE
v_sal NUMBER(4);
v_ename emp.ename%TYPE := '&ename';
BEGIN
SELECT sal
INTO v_sal
FROM emp
WHERE ename = v_ename;

DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);

EXCEPTION
WHEN others THEN
DBMS_OUTPUT.PUT_LINE ('Error executing program.....please contact support team');

END;
/


161

DECLARE
v_sal NUMBER(4);
v_ename emp.ename%TYPE := '&ename';
BEGIN
SELECT sal
INTO v_sal
FROM emp
WHERE ename = v_ename;

DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);

EXCEPTION

WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('Employee doesnot exist');


WHEN others THEN
DBMS_OUTPUT.PUT_LINE ('Error executing program.....please contact support team');

END;

Use of SQLERRM
It can be used in exception handling section to know the Oracle error code and message that is causing
an error
DECLARE
v_sal NUMBER(4);
v_ename emp.ename%TYPE := '&ename';
BEGIN
SELECT sal
162

INTO v_sal
FROM emp
WHERE ename = v_ename;
DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);
EXCEPTION
WHEN others THEN
DBMS_OUTPUT.PUT_LINE ('Error executing program.....please contact support team');
DBMS_OUTPUT.PUT_LINE (SQLERRM);
END;








Use of SQLCODE

DECLARE
v_sal NUMBER(4);
v_ename emp.ename%TYPE := '&ename';
BEGIN
SELECT sal
INTO v_sal
FROM emp
WHERE ename = v_ename;

DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);
EXCEPTION
WHEN others THEN
IF SQLCODE = 100 THEN
DBMS_OUTPUT.PUT_LINE ('Invalid employee...Please enter existing employee
name');
END IF;
END;
163

User-Defined Exceptions
1. They are declared by the programmers
2. They must be raised explicitly as Oracle will not RAISE them until they are associated with an
Oracle error code using EXCEPTION_INIT
3. EXCEPTION_INIT is a pre compiler directive used to map user defined exception to the Oracle
error code

DECLARE
abcd EXCEPTION;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In PL/SQL block');
RAISE abcd;

EXCEPTION
WHEN abcd THEN
DBMS_OUTPUT.PUT_LINE ('In user defined exception');
END;

Imp Points
1. User defined exceptions can have same name as pre-defined exceptions
2. In this case if you want both exception handlers then you can precede pre-defined exception
handler name with the keyword STANDARD

DECLARE
no_data_found EXCEPTION;
v_sal NUMBER(4);
BEGIN
SELECT sal
INTO v_sal
FROM emp
WHERE ename = '&ename';
164

DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);
RAISE no_data_found;
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('In user defined exception');

WHEN STANDARD.no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('Invalid employee...Please enter existing employee name');
END;

NAMING NAMELESS EXCEPTION

Exception_init – preprocessor/precompiler directive can be used to name the nameless exception
Syntax
PRAGMA exception_init(<exception_name>, <error_code>)

Execute the following program when records are already locked from other session
DECLARE
CURSOR cur_emp IS
SELECT job
FROM emp FOR UPDATE NOWAIT;
v_incr_amt NUMBER(6);
record_locked EXCEPTION;
PRAGMA exception_init(record_locked, -00054);
BEGIN
FOR rec_emp IN cur_emp
LOOP
IF rec_emp.job = 'SALESMAN'
THEN
v_incr_amt := 1000;
ELSIF rec_emp.job = 'CLERK'
THEN
v_incr_amt := 1200;
ELSIF rec_emp.job = 'ANALYST'
THEN
165

v_incr_amt := 2000;
ELSIF rec_emp.job = 'MANAGER'
THEN
v_incr_amt := 1500;
ELSIF rec_emp.job = 'PRESIDENT'
THEN
v_incr_amt := 3000;
ELSE
v_incr_amt := 900;
END IF;
UPDATE emp
SET sal = sal + v_incr_amt
WHERE CURRENT OF cur_emp;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Salary Increase Done');
EXCEPTION
WHEN record_locked THEN
DBMS_OUTPUT.PUT_LINE ('Error executing program...pls try after some time. If error
continues then report to support team');
END;


Exception handling and nested blocks

1. Can statements of nested block raise an exception handled in parent block?
YES




DECLARE
v_sal emp.sal%TYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Parent Block');

BEGIN
166

SELECT sal
INTO v_sal
FROM emp
WHERE ename = '&ename';

DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);
END;

DBMS_OUTPUT.PUT_LINE ('In Parent...After nexted block');

EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('In PARENT no data found');

END;
2. Can statements of parent block raise an exception handled in nested block?
NO
3. Can nested block and parent block handle the same exception? If yes then statements of nested
block will raise exception handled in nested block, and statements in parent block will raise
from parent block

DECLARE
v_sal emp.sal%TYPE;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Parent Block');

BEGIN
SELECT sal
167

INTO v_sal
FROM emp
WHERE ename = '&ename';

DBMS_OUTPUT.PUT_LINE ('Salary Is: ' || v_sal);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('In nested no data found');
END;

DBMS_OUTPUT.PUT_LINE ('In Parent...After nexted block');

EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('In PARENT no data found');

END;











168

Sub-Programs
What is a sub-program?
1. It an unit/routine which is used to club logically related statements
2. In Oracle a sub-program is called as a named PL/SQL block
3. There are two types of sub-program
a. FUNCTION – MUST have a return statement at the exit point to return a value
b. PROCEDURE – Does not return a value with RETURN statement
4. They can be stored inside database (called as stored subprograms) or they can be local as well

LOCAL Sub-Programs
These sub-programs can be declared and defined inside –
1. Anonymous PL/SQL block
2. Stored Procedure
3. Stored Function
4. Package
5. Database Trigger

Syntax of procedure
PROCEDURE <name> [(<parameters>)] IS
[<local declaration>]
BEGIN
<pl/sql statements>
[EXCEPTION
<exception_handler>]
END [<name>];

Syntax of function
FUNCTION <name> [(<parameters>)] RETURN <data_type> IS
[<local declaration>]
BEGIN
<pl/sql statements>
[EXCEPTION
169

<exception_handler>]
END [<name>];

And at exit point of function, there MUST BE a RETURN statement returning a value of the <data_type>
mentioned in declaration

Examples of Procedures
DECLARE
PROCEDURE p1 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1');
END;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Block');
p1;
DBMS_OUTPUT.PUT_LINE ('Again in block');
END;
/

DECLARE
PROCEDURE P2; -- Forward Declaration to avoid compilation error
PROCEDURE p1 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1');
p2;
DBMS_OUTPUT.PUT_LINE('IN p1 again');
END p1;

170

PROCEDURE p2 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p2');
END;

BEGIN
DBMS_OUTPUT.PUT_LINE ('In Block');
p1;
DBMS_OUTPUT.PUT_LINE ('In block again');
END;
/

Passing parameters to procedures
DECLARE
PROCEDURE p1 (p_temp number) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || p_temp);
END p1;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Block');
p1(100);
DBMS_OUTPUT.PUT_LINE ('In block again');
END;
/
Declarations of the main block should be prior to the definition of the local sub-program else Oracle
will generate the compilation error –


171

DECLARE
v_cnt NUMBER := 5000;

PROCEDURE p1 (p_temp number) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || p_temp);
END p1;
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Block');
p1(v_cnt);
DBMS_OUTPUT.PUT_LINE ('In block again');
END;
/

You can provide DEFAULT value to call sub-program without passing parameter

DECLARE
v_cnt NUMBER := 5000;

PROCEDURE p1 (p_temp number DEFAULT 300) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || p_temp);
END p1;
BEGIN
p1(v_cnt);
p1;
END;

172


Declarations of the block can be accessed by the local sub-programs defined inside that block –

DECLARE
v_cnt NUMBER := 5000;

PROCEDURE p1 IS
BEGIN
v_cnt := 7000;
END p1;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before Call :' || v_cnt);
p1;
DBMS_OUTPUT.PUT_LINE('After Call :' || v_cnt);
END;
/
Example of function
DECLARE
v_temp NUMBER;
FUNCTION add_val (p1 NUMBER, p2 NUMBER) RETURN NUMBER IS
BEGIN
RETURN p1+p2;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Addition is : ' || add_val(100,200) );
v_temp := add_val(500,200);
DBMS_OUTPUT.PUT_LINE('Addition is : ' || v_temp);
END;
173

/

Two and more sub-programs can have same name as long as signature (total number of parameters
or/and data types) differs

DECLARE
PROCEDURE p1 (x NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
END p1;

PROCEDURE p1 (x NUMBER, y NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x || ' ' ||y);
END p1;

PROCEDURE p1(x VARCHAR2) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
END p1;
BEGIN
p1(100,200);
p1(200);
p1('Sachin');
END;
Using association operator (for named parameter passing)
DECLARE
PROCEDURE p1 (x NUMBER, y NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x || ' ' ||y);
END p1;
BEGIN
p1(y=>100,x=>200);
END;


174

Parameter Passing Modes

1. There are 3 parameter passing modes. They are –
 IN (Default)
 OUT
 IN OUT
2. They determine the behavior of the formal parameter
3. They decide if you can read/write the values of/to the formal parameters

IN OUT IN OUT
You can only read the
value, can not change the
value of the formal
parameter
You cannot read the value
unless you assign the value.
After assignment you can
read the value (post
8.0.4ver).
You can read the value of
formal parameter as well as
you can assign the value
Actual parameter can be a
constant, variable or an
expression
Actual parameter MUST BE
a variable
Actual parameter MUST BE
a variable
Call by value – Value of
actual parameter is copied
into formal parameter
Call BY Reference – Formal
parameter and actual
parameter, both share the
same memory location. But
if you don't assign the value
to the formal parameter,
actual also will have value
of NULL. If subprograms
return with an error, actual
parameters will not have
the same value as the
formal parameter
Call by value – Value of
actual parameter is copied
into formal parameter and
then of formal into actual
when subprogram returns
the control without any
error

IMP NOTE:
1. Actual parameters will get the values copied from Formal parameters if “CALLED Sub-program”
is returning a control without any errors, else Actual parameters will be NULL.
175


DECLARE
v_temp NUMBER(5) := 100;
PROCEDURE p1 (x IN NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);

END;
BEGIN

p1(v_temp + 200);

END;
/
DECLARE
v_temp NUMBER(5) := 100;
PROCEDURE p1 (x IN NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
x:=7000;
END;
BEGIN

p1(v_temp + 200);

END;
DECLARE
v_temp NUMBER := 9000;
176

PROCEDURE p1 (x OUT NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
x := 7000;
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before P1: ' || v_temp);
p1(v_temp);
DBMS_OUTPUT.PUT_LINE('After P1: ' || v_temp);
END;
/
DECLARE
v_temp NUMBER := 9000;
PROCEDURE p1 (x OUT NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1');
--x := 7000;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before P1: ' || v_temp);
p1(v_temp);
DBMS_OUTPUT.PUT_LINE('After P1: ' || v_temp);
END;
/
DECLARE
v_temp CONSTANT NUMBER := 9000;
PROCEDURE p1 (x OUT NUMBER) IS
177

BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1');
x := 7000;
END;
BEGIN
p1(v_temp);
END;
/

DECLARE
v_temp NUMBER := 9000;
PROCEDURE p1 (x IN OUT NUMBER) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
x := 7000;
DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before P1: ' || v_temp);
p1(v_temp);
DBMS_OUTPUT.PUT_LINE('After P1: ' || v_temp);
END;
/

DECLARE
v_temp NUMBER := 9000;
PROCEDURE p1 (x IN OUT NUMBER) IS
BEGIN
178

DBMS_OUTPUT.PUT_LINE('IN p1 :' || x);
--x := 7000;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before P1: ' || v_temp);
p1(v_temp);
DBMS_OUTPUT.PUT_LINE('After P1: ' || v_temp);
END;
/



















179

Stored PL/SQL Program Units

1. They are schema objects that are stored in the database
2. The following are the types of stored PL/SQL program unit –
a. Procedure
b. Function
c. Package
d. Database Trigger

Stored Procedures

CREATE OR REPLACE PROCEDURE <name> [(<parameters>)] IS | AS
[<local declaration>]
BEGIN
<pl/sql statements>
[EXCEPTION
<exception_handler>]
END [<name>];

1. When you get message "Procedure Created" – Oracle stores the source code into the data
dictionary along with the object code. One copy of object code is also stored in the shared pool
2. When you get message "Procedure Created with compilation error" – Oracle stores the source
code into the data dictionary along with the compilation errors
3. user_source can be used to retrieve source code and user_errors for retrieving errors

-- Learning Stored Procedures
CREATE OR REPLACE PROCEDURE P1 AS
BEGIN
DBMS_OUTPUT.PUT_LINE('In stored proc P1');
END;
/

SELECT text
FROM user_source
WHERE name = 'P1'
/

-- To check errors

180

CREATE OR REPLACE PROCEDURE P1 AS
BEGIN
DBMS_OUTPUT.PUT_LINE('In stored proc P1);
END;
/


SELECT text
FROM user_errors
WHERE name = 'P1'
/

 Please create the proc successfully for below testing –

Note: stored sub-programs can be called from SQL*PLUS, Anonymous PL/SQL block, other
subprograms, database trigger, front end program. But for UNIT testing, developer generally writes
anonymous PL/SQL block

To call from SQL*PLUS you can use EXECUTE (EXEC)
>EXEC P1

Anonymous PL/SQL block
BEGIN
P1;
END;
/
If there is a local sub-program by the same name then precedence will be given to the local one.
<schema_name>. can be used to call the stored sub-program when local is having the same name
DECLARE
PROCEDURE p1 IS
BEGIN
DBMS_OUTPUT.PUT_LINE('In LOCAL proc P1');
END;
BEGIN
HR.p1;
p1;
END;
/


181

Write a procedure get_salary which will accept empno as a parameter and will give you ename, sal,
comm and gross sal of the given employee

-- File Name : get_salary.sql
-- Procedure Name : get_salary
-- Author : abc
-- Created On : 16-Jan-2011
-- Description : This procedure accepts employee number as a input and gives ename, sal, comm and
gross salary of that employee

CREATE OR REPLACE PROCEDURE get_salary
(
pi_empno IN emp.empno%TYPE,
po_ename OUT emp.ename%TYPE,
pio_sal IN OUT emp.sal%TYPE,
pio_comm IN OUT emp.comm%TYPE,
po_gross OUT NUMBER
) AS
BEGIN
SELECT ename, sal, comm
INTO po_ename, pio_sal, pio_comm
FROM emp
WHERE empno = pi_empno;

po_gross := pio_sal + NVL(pio_comm,0);

END;
/
Calling program to UNIT test the above program

DECLARE
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
v_comm emp.comm%TYPE;
v_gross NUMBER;
BEGIN
get_salary
(
&empno,
v_ename,
v_sal,
182

v_comm,
v_gross
);

DBMS_OUTPUT.PUT_LINE ('Details are : ' || v_ename || ' '|| v_sal || ' '||
v_comm || ' '|| v_gross);
END;
/

In the above program, exception handling is neither done in called program nor in calling program.
Industry practice is that exception handling is done in the called programs. Also in such cases
communication between called program and calling program is done using two additional
parameters i.e. error_code and error_msg.

-- File Name : get_salary.sql
-- File Name : get_salary.sql
-- Procedure Name : get_salary
-- Author : abc
-- Created On : 16-Jan-2011
-- Description : This procedure accepts employee number as a input and gices ename, sal,
-- comm and gross salary of that employee

CREATE OR REPLACE PROCEDURE get_salary
(
pi_empno IN emp.empno%TYPE,
po_ename OUT emp.ename%TYPE,
pio_sal IN OUT emp.sal%TYPE,
pio_comm IN OUT emp.comm%TYPE,
po_gross OUT NUMBER,
po_error_code OUT VARCHAR2,
po_error_msg OUT VARCHAR2
) AS
BEGIN
SELECT ename, sal, comm
INTO po_ename, pio_sal, pio_comm
FROM emp
WHERE empno = pi_empno;

po_gross := pio_sal + NVL(pio_comm,0);
po_error_code := '00';

183

EXCEPTION
WHEN no_data_found THEN
po_error_code := '99';
po_error_msg := 'INVALID EMPNO...please enter existing empno';

WHEN others THEN
po_error_code := '99';
po_error_msg := 'Error Executing Get_Salary....'|| SUBSTR(SQLERRM,10);

END;
/

Calling program is also changed

DECLARE
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
v_comm emp.comm%TYPE;
v_gross NUMBER;
v_error_code VARCHAR2(2);
v_error_msg VARCHAR2(1000);
BEGIN
get_salary
(
&empno,
v_ename,
v_sal,
v_comm,
v_gross,
v_error_code,
v_error_msg
);

IF v_error_code = '00' THEN
DBMS_OUTPUT.PUT_LINE ('Details are : ' || v_ename || ' '|| v_sal || ' '||
v_comm || ' '|| v_gross);
ELSE
DBMS_OUTPUT.PUT_LINE (v_error_msg);
END IF;
END;
/
184

Stored Functions

CREATE OR REPLACE FUNCTION <name> [(<parameters>)] RETURN <data_type> IS|AS
[<local declaration>]
BEGIN
<pl/sql statements>
[EXCEPTION
<exception_handler>]
END [<name>];

Write a function get_count which accepts job as a parameter and returns total no of employees
working on that job
CREATE OR REPLACE FUNCTION get_count
(
pi_job IN emp.job%TYPE
) RETURN NUMBER AS

v_cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO v_cnt
FROM emp WHERE JOB = PI_JOB;

RETURN v_cnt;
END;
/

Calling the above program from SQL*PLUS
 VARIABLE v_temp
 EXEC :v_temp := get_count('MANAGER')
 PRINT v_temp

Function also can be called from SQL statements –
 SELECT get_count('MANAGER') FROM dual
 SELECT empno, ename, job, get_count(job) FROM emp
 SELECT empno, ename, job, get_count(job) FROM emp
WHERE get_count(job) > 2

Calling the above program using Anonymous block
DECLARE
v_temp NUMBER;
BEGIN
v_temp := get_count('&job');
185

DBMS_OUTPUT.PUT_LINE (v_temp);
END;
/

Create a function chk_deptno which will accept deptno as a parameter and will return TRUE if that
dept no exists in DEPT table else returns FALSE
CREATE OR REPLACE FUNCTION chk_deptno
(
pi_deptno IN dept.deptno%TYPE
) RETURN BOOLEAN AS

v_cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO v_cnt
FROM dept WHERE deptno = pi_deptno;

IF v_cnt > 0 THEN
RETURN TRUE;
END IF;

RETURN FALSE;
END;
/


OR
CREATE OR REPLACE FUNCTION chk_deptno
(
pi_deptno IN dept.deptno%TYPE --90
) RETURN BOOLEAN AS

v_flag CHAR;
BEGIN
SELECT 'X' INTO v_flag
FROM dept WHERE deptno = pi_deptno;
RETURN TRUE;

EXCEPTION
WHEN no_data_found THEN
RETURN FALSE;
END;
186

/

OR
CREATE OR REPLACE FUNCTION chk_deptno
(
pi_deptno IN dept.deptno%TYPE --90
) RETURN BOOLEAN AS

CURSOR c1 IS
SELECT 'X' FROM dept
WHERE deptno = pi_deptno;
v_flag CHAR;
BEGIN
OPEN c1;
FETCH c1 INTO v_flag;
CLOSE c1;

IF v_flag = 'X' THEN
RETURN TRUE;
END IF;
RETURN FALSE;
END;
/

NOTE: As per few Oracle books SELECT statement using CURSOR runs faster than SELECT .. INTO ..
because –
For SELECT .. INTO .. Oracle checks for three Exceptions i.e. no_data_found, too_many_rows and
value_error but for CURSOR it doesnot check for these errors.



Write a procedure add_employee which accepts –
1. Employee name, salary, job and deptno values from calling program,
2. Checks if deptno value is existing in dept table if yes then inserts a record into emp table. While
inserting the record, employee number should be automatically generated and should be returned
back to the calling program.
3. If deptno does not exists then should raise an user generated error and return the control back to
the calling program with that error

 Please create the sequence first

187

CREATE OR REPLACE PROCEDURE add_employee
(
po_empno OUT emp.empno%TYPE,
pi_ename IN emp.ename%TYPE,
pi_sal IN emp.sal%TYPE,
pi_job IN emp.job%TYPE,
pi_deptno IN emp.deptno%TYPE
) AS
BEGIN
IF chk_deptno(pi_deptno) = TRUE THEN
INSERT INTO emp (empno,ename,sal,job,deptno)
VALUES (seq_empno.NEXTVAL, pi_ename, pi_sal, pi_job, pi_deptno)
RETURNING empno INTO po_empno;
ELSE
RAISE_APPLICATION_ERROR(-20000,'INVALID DEPTNO....Please enter existing dept');
END IF;
END;
/
-- Calling program for add_employee

DECLARE
v_empno emp.empno%TYPE;
BEGIN
add_employee (v_empno,
'&ename',
&sal,
'&job',
&deptno);
DBMS_OUTPUT.PUT_LINE ('Record Inserted Successfully...empno is: '||v_empno);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
END;
/







188

RAISE_APPLICATION_ERROR

1. It is used to generate the user defined run time error
2. It stops an execution of the PL/SQL block and returns the control to calling program with that
error (assuming error is not handled in the called program)
3. It accepts two parameters –
a. Error_code – Should be within range of -20000 to -20999
b. Error_message – Any string containing the message

Write a procedure increase_sal which will accept empno and amount and will increase the salary of
the given employee by the given amount. If empno is not existing then it should return message to
the calling program and ask to enter the valid empno else should return the current salary to the
calling program

CREATE OR REPLACE PROCEDURE update_salary
(
pi_empno IN emp.empno%TYPE,
pi_amt IN emp.sal%TYPE,
po_sal OUT emp.sal%TYPE,
po_error_code OUT VARCHAR2,
po_error_msg OUT VARCHAR2
) AS
BEGIN
UPDATE emp
SET sal = sal + pi_amt
WHERE empno = pi_empno
RETURNING sal INTO po_sal;

IF SQL%ROWCOUNT > 0 THEN
po_error_code := '00';
ELSE
RAISE_APPLICATION_ERROR(-20001,'INVALID empno....please enter existng empno');
END IF;
EXCEPTION
WHEN OTHERS THEN
po_error_code := '99';
po_error_msg := SUBSTR(SQLERRM,12);
END;
/



189


-- Calling program for update_salary

DECLARE
v_sal emp.sal%TYPE;
v_error_code VARCHAR2(2);
v_error_msg VARCHAR2(1000);
BEGIN
update_salary (&empno, &amount, v_sal, v_error_code, v_error_msg);
IF v_error_code = '00' THEN
DBMS_OUTPUT.PUT_LINE ('Record Updated Successfully...salary is: '||v_sal);
ELSE
DBMS_OUTPUT.PUT_LINE (v_error_msg);
END IF;
END;
/

Advantages of stored sub-programs
Other than the advantages given in sub-program (local) topic, the following are the advantages of the
stored sub-program
1. Performance Improvement –
a. Since they are stored at DB server side, network traffic and round trips are reduced
which helps to improve the performance
b. One copy of object code is shared among all connected sessions (having privilege to
execute the procedure)
2. Abstraction – The implementation details of these sub-programs are hidden from calling
programs. So when changes are required in the business logic, only these sub-programs will
need a change and not the calling programs
3. Security – By creating sub-programs to modify the data of table you can provide security to the
table and its data. Instead of granting access of these tables to other users or directly accessing
these tables from front end program, you can allow them to call these sub-programs which in
turn will manipulate the data from these tables.






190

Packages



1. Package is an unit which encapsulates logically related members
2. Package is created in two parts
a. Specification
b. Body
3. All members declared in the specification can be accessed from outside programs (front end,
stored procedure, functions, Database trigger etc)
4. Package body can be created successfully (w/o any error) only if all sub-programs declared in
the specification are defined inside it
5. Members not declared in specification but declared or defined inside body, can not be accessed
from outside programs. They can be accessed only within the same package
6. To access the members of the packages you can use <package_name>.<member_name>

Syntax
Package Specification
CREATE [OR REPLACE] PACKAGE <name> AS
<Declaration of members>
END <name>;

Package Body
CREATE [OR REPLACE] PACKAGE BODY <name> AS
<Definition of members>
END <name>;

Create a package employee which has get_employees procedure.
This procedure must accept deptno and should return empno, ename, sal & job of all employees
working in that deptno. In case of non existing deptno, it should send the proper error message




<declaration of variables, constants,
exceptions, cursors etc>
<declaration of procedures & functions>
Specification
<MUST have definition for all those
procedures and functions declared
In the specification>
<declaration & definition of procedures
& functions NOT declared in spec>
<declaration of variables, constants,
exceptions, cursors etc>

Body
191

CREATE OR REPLACE PACKAGE employee AS
TYPE emp_ty IS RECORD
(
empno emp.empno%TYPE,
ename emp.ename%TYPE,
sal emp.sal%TYPE,
job emp.job%TYPE
);

TYPE emp_tab IS TABLE OF emp_ty INDEX BY BINARY_INTEGER;

PROCEDURE get_employee
(
pi_deptno IN emp.deptno%TYPE,
po_emps OUT emp_tab,
po_error_code OUT VARCHAR2,
po_error_msg OUT VARCHAR2
);
END;
/


CREATE OR REPLACE PACKAGE BODY employee AS
PROCEDURE get_employee
(
pi_deptno IN emp.deptno%TYPE, --40
po_emps OUT emp_tab,
po_error_code OUT VARCHAR2,
po_error_msg OUT VARCHAR2
) IS
i NUMBER := 1;
CURSOR cur_emp IS
SELECT empno, ename, sal, job FROM emp
WHERE deptno = pi_deptno;
BEGIN
IF chk_deptno (pi_deptno) THEN
FOR rec_emp IN cur_emp
LOOP
po_emps(i).empno := rec_emp.empno;
po_emps(i).ename := rec_emp.ename;
po_emps(i).sal := rec_emp.sal;
192

po_emps(i).job := rec_emp.job;
i := i + 1;
END LOOP;
po_error_code := '00';
ELSE
po_error_code := '99';
po_error_msg := 'INVALID DEPTNO....please enter existing deptno';
RETURN;
END IF;

IF i = 1 THEN
po_error_code := '99';
po_error_msg := 'NO Employees are working in this department';
END IF;

END get_employee; -- End of the procedure
END employee; -- End of the package
/

-- Calling program for get_employee procedure of employee package

DECLARE
v_emps employee.emp_tab;
v_error_code VARCHAR2(2);
v_error_msg VARCHAR2(1000);
BEGIN
employee.get_employee (&deptno, v_emps,v_error_code,v_error_msg);
IF v_error_code = '00' THEN
FOR i IN 1..v_emps.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE (v_emps(i).empno || ' '||
v_emps(i).ename || ' '||
v_emps(i).sal || ' '||
v_emps(i).job);
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE (v_error_msg);
END IF;

END;
/
193

Function chk_deptno also can be a part of package, if it is not called from outside

CREATE OR REPLACE PACKAGE BODY employee AS


FUNCTION chk_deptno
(
pi_deptno IN dept.deptno%TYPE --90
) RETURN BOOLEAN AS

v_flag CHAR;
BEGIN
SELECT 'X' INTO v_flag
FROM dept WHERE deptno = pi_deptno;
RETURN TRUE;

EXCEPTION
WHEN no_data_found THEN
RETURN FALSE;
END chk_deptno;

PROCEDURE get_employee
(
pi_deptno IN emp.deptno%TYPE, --40
po_emps OUT emp_tab,
po_error_code OUT VARCHAR2,
po_error_msg OUT VARCHAR2
) IS
i NUMBER := 1;
CURSOR cur_emp IS
SELECT empno, ename, sal, job FROM emp
WHERE deptno = pi_deptno;
BEGIN
IF chk_deptno (pi_deptno) THEN
FOR rec_emp IN cur_emp
LOOP
po_emps(i).empno := rec_emp.empno;
po_emps(i).ename := rec_emp.ename;
po_emps(i).sal := rec_emp.sal;
po_emps(i).job := rec_emp.job;
i := i + 1;
194

END LOOP;
po_error_code := '00';
ELSE
po_error_code := '99';
po_error_msg := 'INVALID DEPTNO....please enter existing deptno';
RETURN;
END IF;

IF i = 1 THEN
po_error_code := '99';
po_error_msg := 'NO Employees are working in this department';
END IF;

END get_employee; -- End of the procedure


END employee; -- End of the package
/























195

REF Cursor
They are used under the following circumstances –
1. When SELECT statement to be associated with Cursor is not same and changes based on
conditions
2. When SELECT statement is dynamic

There are two types of REF Cursor –
1. Strongly Typed – Row Type is fixed. SELECT statement used to open this Cursor MUST have
same Row Type as of Cursor. If not then opening of cursor will result in an error
2. Weakly Typed – No fixed Row Type. So there is no restriction on the SELECT statement Row
Type.
Weakly Typed Ref Cursor
TYPE <type_name> IS REF CURSOR

EX - TYPE cur_ty IS REF CURSOR;

Strongly Typed Ref Cursor
TYPE <type_name> IS REF CURSOR RETURN < type>

EX - TYPE cur_ty IS REF CURSOR RETURN emp%ROWTYPE;

In the above examples cur_ty is REF Cursor type and not the actual REF Cursor. Using that type you
need to declare the Cursor as below -
Cur_emp cur_ty;

To open the Ref Cursor syntax is as below -
OPEN <ref cursor> FOR <SELECT statement>
EX – OPEN cur_emp FOR SELECT * FROM emp;

CREATE OR REPLACE PACKAGE employee AS

TYPE cur_ty is REF CURSOR;

PROCEDURE get_employee
(
pi_deptno IN emp.deptno%TYPE,
po_emps OUT cur_ty,
po_error_code OUT VARCHAR2,
po_error_msg OUT VARCHAR2
);
END;
196

/
CREATE OR REPLACE PACKAGE BODY employee AS


FUNCTION chk_deptno
(
pi_deptno IN dept.deptno%TYPE --90
) RETURN BOOLEAN AS

v_flag CHAR;
BEGIN
SELECT 'X' INTO v_flag
FROM dept WHERE deptno = pi_deptno;
RETURN TRUE;

EXCEPTION
WHEN no_data_found THEN
RETURN FALSE;
END chk_deptno;

PROCEDURE get_employee
(
pi_deptno IN emp.deptno%TYPE, --40
po_emps OUT cur_ty,
po_error_code OUT VARCHAR2,
po_error_msg OUT VARCHAR2
) IS
BEGIN
IF chk_deptno (pi_deptno) THEN
OPEN po_emps
FOR SELECT empno, ename, sal, job
FROM emp WHERE deptno = pi_deptno;
po_error_code := '00';
ELSE
po_error_code := '99';
po_error_msg := 'INVALID DEPTNO....please enter existing deptno';
END IF;
END get_employee; -- End of the procedure


END employee; -- End of the package
197

/

Calling get_employee from SQL*PLUS
>VARIABLE v_error_code VARCHAR2(2)
>VARIABLE v_error_msg VARCHAR2(200)
>VARIABLE v_emps REFCURSOR
> EXEC employee.get_employee(10, :v_emps, :v_error_code, :v_error_msg)
> PRINT v_emps

Calling get_employee from anonymous PL/SQL block
DECLARE
v_emps employee.cur_ty;
v_error_code VARCHAR2(2);
v_error_msg VARCHAR2(1000);
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
v_job emp.job%TYPE;
BEGIN
employee.get_employee (&deptno, v_emps,v_error_code,v_error_msg);
IF v_error_code = '00' THEN
LOOP
FETCH v_emps INTO v_empno, v_ename, v_sal, v_job;
EXIT WHEN v_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (v_empno|| ' '||v_ename||' '||
v_sal || ' '|| v_job);
END LOOP;
CLOSE v_emps;
ELSE
DBMS_OUTPUT.PUT_LINE (v_error_msg);
END IF;

END;
/

Assignment

Please modify the employee package in such a way that get_employee procedure should return '99' as
error_code and error_msg as "No employee is working in this department" when valid deptno is
passed as a parameter but does not have employees working in it.

198

Advantages of packages

1. Encapsulation
2. Memory Management (Performance Improvement)


Scope and lifetime of declarations (such as variables) made in procedure, function and package

1. Every session has its own copy of these declarations which is stored in PGA of that session.
2. Scope means accessibility and lifetime means the time they retain their values
3. Scope and lifetime of the declarations made in procedures and functions is within the same
PL/SQL block. Once control comes out of that procedure or function they cannot be accessed
4. The following is the scope and lifetime of packaged declarations (specification)
a. Scope – These declarations can be accessed outside the package and in programs like
front end program, stored procedure, stored function etc. which is either written by
same user or the user who has an EXECUTE privilege on this package
b. Lifetime – These declarations retain their values as long as session continues or their
values are overwritten


Valid procedures, functions, packages, Database Triggers can go in INVALID state under the following
circumstances –

1. When referenced object is dropped
2. When referenced object is altered
3. When privileges of the referenced objects are revoked by the owner of those objects from the
creator of these stored units


What is the difference between DROP and then CREATE and CREATE OR REPLACE option?

When you use combination of DROP and CREATE, ORACLE removes all information about that stored
object, like privileges granted on that object to other users, from data dictionary.

CREATE OR REPLACE keeps all such information and replaces only source code and object code

Using ALTER statement

You can use ALTER statement to compile the source code stored in the data dictionary. Generally this is
done when object is in INVALID state

199

Syntax

ALTER PROCEDURE <name> COMPILE
ALTER FUNCTION <name> COMPILE
ALTER PACKAGE <name> COMPILE – compiles only package specification
ALTER PACKAGE <name> COMPILE BODY – compiles package body

Using DROP statement
Syntax

DROP PROCEDURE <name>
DROP FUNCTION <name>
DROP PACKAGE BODY <name>
DROP PACKAGE <name> - Drops entire package (spec as well as body)
















200

Database Triggers


1. It is a stored PL/SQL block having an event associated to it
2. It is implicitly executed by Oracle, whenever that event takes place
3. You can not execute this block (trigger) like you execute procedure or function
4. Triggers can be applied only on the tables but they are also applicable to the views created on
that table

Syntax

CREATE [OR REPLACE] TRIGGER <name>
<trigger_timing> <trigger_event> ON <table_name>
[FOR EACH ROW]
[WHEN <condition>]
[DECLARE
<local_declarations>]
BEGIN
<Pl/sql statements>
[EXCEPTION
<exception handler>]
END [<name>];

In the above syntax the lines marked in BOLD are the trigger specification and underlined are trigger
body


<trigger_timing> = either BEFORE or AFTER
<trigger_event> = either INSERT or UPDATE or DELETE (you can either mention one, two or all of
them)

Example
CREATE OR REPLACE TRIGGER learn_trig
BEFORE INSERT ON my_emp
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Insert trigger');
END;
/

201

1. Up on successful creation of trigger, Oracle stores source code along with one copy of object code
into the data dictionary and one copy of object code is stored in shared pool
2. Information about trigger (like trigger event, body etc) can be retrieved from user_triggers
3. If there are any compilation errors (PL/SQL block) then they can be retrieved from user_errors

SELECT triggering_event, trigger_body from user_triggErs where trigger_name = 'LEARN_TRIG'
/

 INSERT INTO my_emp VALUES (1001,'SACHIN',5000,10);
 INSERT INTO my_emp SELECT empno, ename, sal, deptno FROM emp;
 INSERT INTO my_emp SELECT empno, ename, sal, deptno FROM emp
WHERE 1=2;

There are two levels of trigger –

1. Statement Level
a. They are fired only ones for the triggering statement irrespective of total number of
records manipulated
b. They are fired even when no records are manipulated by the triggering statement
2. Row Level –
a. Trigger is row level when FOR EACH ROW is added in trigger specification
b. They are fired ones for every record manipulated by the triggering statement
c. They are NOT fired when no records are manipulated by the triggering statement

CREATE OR REPLACE TRIGGER learn_trig
BEFORE INSERT ON my_emp
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE ('In Insert trigger');
END;
/

Possible combination of events
BEFORE INSERT Statement
AFTER UPDATE Row
DELETE

1. There are total 12 possible events
2. If you want to handle each event separately then you will need 12 triggers but do handle all
events with minimum number of events, you will need 4 triggers

Triggering Statement
It is a DML statement that causes a trigger to fire
202

Conditional Predicates
INSERTING
UPDATING
DELETING

These can be used in the body of database trigger to determine the event causing trigger to fire.
CREATE OR REPLACE TRIGGER learn_trig
BEFORE INSERT OR UPDATE OR DELETE ON my_emp
FOR EACH ROW
BEGIN
IF INSERTING THEN
DBMS_OUTPUT.PUT_LINE ('Inserting Data');
ELSIF UPDATING THEN
DBMS_OUTPUT.PUT_LINE ('Updating Data');
ELSE
DBMS_OUTPUT.PUT_LINE ('Deleting Data');
END IF;

END;
/

Sequence of trigger execution
1. BEFORE Statement trigger
2. LOOP for executing triggering statement and manipulating records
a. BEFORE row trigger
b. Locks the record and manipulates the same
c. AFTER row trigger
3. AFTER statement trigger

Use of NEW and OLD

1. They can be used to refer to the values of the record that is being processed.
2. They have the same ROWTYPE as the table whose values you are referring in the body of
database triggers


203

DML Statement NEW OLD
INSERT YES NO (will be NULL)
UPDATE YES YES
DELETE NO (will be NULL) YES

In case of UPDATE values of NEW and OLD will be same unless they are changed.



CREATE OR REPLACE TRIGGER learn_trig
BEFORE INSERT OR UPDATE OR DELETE ON my_emp
FOR EACH ROW
BEGIN
DBMS_OUTPUT.PUT_LINE ('OLD Values : '||:OLD.empno|| ' ' || :OLD.ename || ' ' ||
:OLD.sal || ' ' || :OLD.deptno);

DBMS_OUTPUT.PUT_LINE ('NEW Values : '||:NEW.empno|| ' ' || :NEW.ename || ' ' ||
:NEW.sal || ' ' || :NEW.deptno);
END;
/

INSERT INTO my_emp VALUES (1007,'SACHIN',70000,20)
/
UPDATE my_emp SET sal = 9000 WHERE empno = 1007
/
DELETE FROM my_emp WHERE empno = 1007
204

Use of Database Triggers
1. TO automatically calculate values for derived columns (either of same table or another table)
2. TO implement referential integrity between the tables belonging to remote databases
3. TO implement complex business rules that are not possible using Integrity Constraints
4. TO prevent invalid transactions
5. To implement security authorizations/audit logs etc

Please create the following table
SQL> DESC MY_EMP
Name
Null? Type
----------------------------------------------------------
---------------------------------- -------- ---------------
----------------------------------------
EMPNO
NUMBER(4)
ENAME
VARCHAR2(10)
SAL
NUMBER(7,2)
DEPTNO
NUMBER(2)
JOB
VARCHAR2(25)
COMM
NUMBER(6,2)

Ex1. Please write a database trigger to automatically calculate the value for comm. column as follow –
1. It should be 5% of the salary
2. It should be auto calculated only for those employees who are working as SALESMAN

CREATE OR REPLACE TRIGGER comm_mani
BEFORE INSERT OR UPDATE OF sal, job ON my_emp
FOR EACH ROW
WHEN (UPPER(NEW.job) = 'SALESMAN')
BEGIN
:NEW.comm := :NEW.sal * 0.05;
END;
/

Execute SELECT * FROM my_emp after each statement below
> INSERT INTO my_emp VALUES (1001,'SACHIN',7000,10,'SALESMAN',NULL);
205

> INSERT INTO my_emp VALUES (1002,'SAURAV',8000,20,'MANAGER',NULL);
> UPDATE my_emp
SET job = 'SALESMAN'
WHERE empno = 1002;
>UPDATE my_emp
SET SAL = 10000
WHERE empno = 1002;
Ex-2 –

Create a table salary as below
Column Name Data Type Length
Empno NUMBER 4
Da NUMBER 8,2
Hra NUMBER 8,2
Ded NUMBER 6,2
NetSal NUMBER 10,2

Write a database trigger which will be fired when record of my_emp table is manipulated and will do
the following –
1. When record is inserted or sal column value is updated –
a. Calculate the values for DA, HRA, DED, NETSAL based on value of sal and comm.
b. DA = 25% of sal, hra = 20% of sal, ded = 6% of sal and netsal = sal+da+hra+comm.-ded
2. When empno value is updated from my_emp table, it should update the empno value from the
salary table
3. When record is deleted frm my_emp, it should delete the record from salary table

CREATE OR REPLACE TRIGGER salary_dml
AFTER INSERT OR UPDATE OF sal, empno OR DELETE ON my_emp
FOR EACH ROW
DECLARE
v_da salary.da%TYPE;
v_hra salary.hra%TYPE;
v_ded salary.ded%TYPE;
v_netsal salary.netsal%TYPE;
BEGIN

IF INSERTING OR UPDATING('sal') THEN
v_da := :NEW.sal * 0.25;
v_hra := :NEW.sal * 0.20;
v_ded := :NEW.sal * 0.06;
v_netsal := :NEW.sal+NVL(:NEW.comm,0)+v_da+v_hra-v_ded;
206

IF INSERTING THEN
INSERT INTO salary(empno,da,hra,ded,netsal)
VALUES(:NEW.empno, v_da, v_hra, v_ded,v_netsal);
ELSE
UPDATE salary
SET da = v_da, hra = v_hra, ded = v_ded, netsal = v_netsal
WHERE empno = :OLD.empno;
END IF;
END IF;

IF UPDATING('empno') THEN
UPDATE salary
SET empno = :NEW.empno
WHERE empno = :OLD.empno;
END IF;

IF DELETING THEN
DELETE FROM salary
WHERE empno = :OLD.empno;
END IF;
END;
/

After each statement please execute SELECT on my_emp and salary
> INSERT INTO my_emp VALUES (1002,'SAURAV',8000,20,'MANAGER',NULL);
> UPDATE my_emp
SET SAL = 10000
WHERE empno = 1002;
> UPDATE my_emp
SET empno = 5001
WHERE empno = 1002;
> UPDATE my_emp
SET empno = 7001,
sal = 15000
WHERE empno = 5001;
 DELETE FROM my_emp WHERE empno = 7001;




207

Trigger Cascading

When statement given in body of a trigger causes another trigger to fire then that is called as Trigger
Cascading

Imp Note – AFTER ROW triggers are slightly more efficient than BEFORE ROW triggers because for
execution of before row triggers, ORACLE reads affected data twice i.e. Trigger body execution and
then again for triggering statement execution. But for after row trigger, it reads affected data only one
time i.e. for triggering statement execution





Ex-3
Write a database trigger to STOP DML operation on my_emp table during no working days and non
working hours

CREATE OR REPLACE TRIGGER stop_dml
BEFORE INSERT OR UPDATE OR DELETE ON my_emp
BEGIN
IF TO_CHAR(SYSDATE,'DY') = 'SAT' OR
TO_CHAR(SYSDATE,'DY') = 'SUN' THEN
RAISE_APPLICATION_ERROR(-20000, 'Can not manipulate on non working days');
ELSIF TO_CHAR(SYSDATE,'HH24:MI') < '09:00' OR
TO_CHAR(SYSDATE,'HH24:MI') > '18:30' THEN
RAISE_APPLICATION_ERROR(-20001, 'Can not manipulate on non working hours');
END IF;
END;
/
Assignment –

1. Create a table job_sal which has the following columns

Column Name Data Type Length
Job_Code Number 2
Losal Number 5
Hisal Number 5

208

Whenever you are inserting or updating record (job,sal) into my_emp table oracle should check
if salary is as per the range specified in job_sal table, if no then that transaction should
not be allowed.

2. Write a database trigger on my_emp table it should be execute whenever you perform DML
operation on my_emp and should insert username, terminal name, DML statement issued by
that user from that terminal & that time into log_table.
To get Terminal use:- userenv(‘terminal’)

3. Find out the reason why commit and rollback cannot be used in the body of the trigger (unless
they are autonomous transactions).

4. What is Table Mutating Error?





INSTEAD OF Triggers

1. They can be created or applied only on the views
2. There are 3 possible events –
a. INSTEAD OF INSERT
b. INSTEAD OF UPDATE
c. INSTEAD OF DELETE
3. In presence of INSTEAD OF trigger on the view, ORACLE executes this trigger when DML
operations are performed on the view and skips the execution of DML operation on the base
table of the view
4. They are ROW Level triggers
5. They are used to make the unmodified view modifiable

Ex
CREATE OR REPLACE view v1 AS
SELECT empno, ename, sal+2000 bonus, deptno
FROM emp
/
The following operations are not allowed
INSERT INTO v1 VALUES (1001,'SACHIN',7000,10)
/
UPDATE V1 SET BONUS = BONUS+2000
/

209

CREATE OR REPLACE TRIGGER v1_mani
INSTEAD OF INSERT OR UPDATE OR DELETE ON v1
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO emp (empno, ename, sal, deptno)
VALUES (:NEW.empno, :NEW.ename, :NEW.bonus-2000, :NEW.deptno);
ELSIF UPDATING THEN
UPDATE emp
SET ename = :NEW.ename,
sal = sal + (:NEW.BONUS - :OLD.bonus),
deptno = :NEW.deptno
WHERE empno = :OLD.empno;
ELSE
DELETE FROM emp
WHERE empno = :OLD.empno;
END IF;
END;
Now try DML operation on V1 and see an impact by performing SELECT operation on V1 as well as emp
table












210

Autonomous Transaction


P1 P2
-- -
- -
- -
-
P2 COMMIT OR ROLLBACK
-
-
-
COMMIT OR ROLLBACK

1. In the above case, P1 is a parent transaction and P2 is a child transaction
2. Child transaction shares the COMMIT dependencies with the parent transaction so whenever
COMMIT or ROLLBACK is issues from P2, it will not only save or cancel the changes made by
itself but also the changes made by Parent Transaction (P1)
3. To avoid this P2 can be marked as Autonomous Transaction
4. To mark the child transaction as Autonomous, you have to use PRAGMA AUTONOMOUS
TRANSACTION statement in the DECLARE section of child transaction.
5. Once child transaction is marked as Autonomous, Oracle pauses parent transaction, initiates
child transaction, does the changes, commit or rollbacks these changes and then resumes
parent transaction
6. You can commit or rollback the parent transaction without impacting the changes made by the
autonomous transaction
7. Changes committed by Autonomous transactions are available to parent transaction only when
TRANSACTION ISOLATION LEVEL is set to READ COMMITTED (By default). If it is set to
SERIALIZABLE then they are not available
8. Changes made by the parent transaction are not available to the Autonomous transaction,
unless they are committed
9. The following can be marked as Autonomous
a. Stored Procedure
b. Stored Function
c. Packaged Procedure or function (entire package can't marked as Autonomous. If you
want all subprograms of that package as Autonomous then you need to mark all of them
individually as Autonomous)
d. Database Trigger
e. Methods of an object type
f. Parent Anonymous Block (Not the nested block)



211

Ex
1. create parts and parts_log table
2. write a database trigger on parts table which will INSERT the record into parts_log table and
also commit that

CREATE TABLE parts
(pno number(2),
pname VARCHAR2(30)
)
/
Now create parts_log having same structure

CREATE OR REPLACE TRIGGER learn_autonomous
AFTER INSERT ON parts
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO parts_log (pno, pname)
VALUES (:NEW.pno, :NEW.pname);
COMMIT;
END;
/

> INSERT INTO parts VALUES (1,'ABC');
> COMMIT;
> SELECT * FROM parts;
> SELECT * FROM parts_log;

> INSERT INTO parts VALUES (2,'PQR');
> SELECT * FROM parts;
> SELECT * FROM parts_log;
> ROLLBACK;
> SELECT * FROM parts;
> SELECT * FROM parts_log;

CREATE OR REPLACE PROCEDURE p1 AS
BEGIN
INSERT INTO emp (empno,ename,sal,deptno)
VALUES (1001, 'ABC', 3500, 10);
p2;
212

UPDATE emp
SET sal = sal + 3500;
COMMIT;
END;
/

Changes made by the parent transaction are not available to the Autonomous transaction, unless
they are committed

CREATE OR REPLACE PROCEDURE p2 AS
v_sal emp.sal%TYPE;
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
SELECT sal INTO v_sal
FROM emp WHERE empno = 1001;
DBMS_OUTPUT.PUT_LINE('Salary IS :' || v_sal);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.PUT_LINE ('parent transaction record not available');
END;
/
> EXEC P1
Native Dynamic SQL

1. When complete text of the SQL statement is not known at the time of compilation is called as
"Dynamic SQL"
2. These statements are formed at runtime and only then their complete text is known
3. This gives you a flexibility to decide upon the schema object NAME, filter conditions and list of
columns at runtime
4. This also allows you to execute DDL, DCL, Session and system control statements from PL/SQL
block
5. These make software components more flexible and increases their reusability
6. All such statements (except for SELECT statement that returns more than one record) are
executed using EXECUTE IMMEDIATE statement. To execute SELECT statement that returns
more than one record, you have to use OPEN …. FOR ….. syntax
7. This feature is available since 8i onwards, prior to this DBMS_SQL package was the only means
to execute dynamic SQL statements
8. Now also DBMS_SQL package can be used, but if you want something easier to use, better in
performance and support for objects and collections then you should use Native Dynamic SQL

Example to learn the syntax


213

DECLARE
v_deptno dept.deptno%TYPE := 50;
v_dname dept.dname%TYPE := 'HR';
v_loc dept.loc%TYPE := 'MUMBAI';
v_sql VARCHAR2(1000);
v_rec_emp emp%ROWTYPE;
v_cnt NUMBER;
v_tname VARCHAR2(30) := '&tablename';
BEGIN
v_sql := 'INSERT INTO dept VALUES (:b_deptno, :b_dname, :b_loc)';
EXECUTE IMMEDIATE v_sql USING v_deptno, v_dname, v_loc;
DBMS_OUTPUT.PUT_LINE('Record Inserted Successfully');

v_sql := 'SELECT * FROM emp WHERE empno = :1';
EXECUTE IMMEDIATE v_sql INTO v_rec_emp USING 1001;
DBMS_OUTPUT.PUT_LINE(v_rec_emp.ename || ' '||v_rec_emp.sal);

v_sql := 'SELECT COUNT(*) FROM '||v_tname;
EXECUTE IMMEDIATE v_sql INTO v_cnt;
DBMS_OUTPUT.PUT_LINE('Total no of records in '||v_tname || ' are : '||v_cnt);

EXECUTE IMMEDIATE 'CREATE TABLE temp1
(empno NUMBER(5),
ename VARCHAR2(25))';

END;
/

Ex-2 Create a function count_rows which will accept the table_name or view name as a parameter and
returns total number of records from that table or view

CREATE OR REPLACE FUNCTION count_rows
(
pi_table_name VARCHAR2
) RETURN NUMBER AS

v_cnt NUMBER;

BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' ||pi_table_name
INTO v_cnt;
214

RETURN v_cnt;
END;
/

Ex-2 Create a procedure drop_object which will accept, kind of object and name of the object and will
drop that object

CREATE OR REPLACE PROCEDURE drop_object
(
pi_kind VARCHAR2,
pi_name VARCHAR2
) AS
BEGIN
EXECUTE IMMEDIATE 'DROP '|| pi_kind || ' '|| pi_name;
DBMS_OUTPUT.PUT_LINE('Object dropped Successfully');
END;
/

> call drop_object('table','temp');
> call drop_object('view,'v1');

Imp Note: By default subprograms are mapped to the schema of the owner and not executor. If you
want them to be mapped to the schema of executor then you should use AUTHID CURRENT_USER
clause as below –

CREATE OR REPLACE PROCEDURE drop_object
(
pi_kind VARCHAR2,
pi_name VARCHAR2
) AUTHID CURRENT_USER AS
BEGIN
EXECUTE IMMEDIATE 'DROP '|| pi_kind || ' '|| pi_name;
DBMS_OUTPUT.PUT_LINE('Object dropped Successfully');
END;
/

Ex-3 Write a procedure delete_rows that accepts – Table_name and condition a parameter and deletes
the record from the given table using the given condition. If condition is not provided then it should
delete all records –


215

CREATE OR REPLACE PROCEDURE delete_rows
(
pi_tname VARCHAR2,
pi_condi VARCHAR2 DEFAULT NULL
) AS
v_sql VARCHAR2(1000);
v_where VARCHAR2(500);
BEGIN
IF pi_condi IS NOT NULL THEN
v_where := ' WHERE '||pi_condi;
END IF;
v_sql := 'DELETE FROM ' || pi_tname||v_where;
EXECUTE IMMEDIATE v_sql;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' Records Deleted');
END;
/

> call delete_rows('emp','sal>3000');
> call delete_rows('emp','job=''CLERK''');
> call delete_rows('salary');

Ex-4 Write a procedure list_employees that accepts the condition as a parameter and displays empno,
ename, sal and job of all employees satisfying that condition. If condition is not passed as a parameter
then it should display all employees
CREATE OR REPLACE PROCEDURE list_employees
(
pi_condi VARCHAR2 DEFAULT NULL
) AS
v_sql VARCHAR2(1000);
v_where VARCHAR2(500);
TYPE cur_ty IS REF CURSOR;
cur_emps cur_ty;
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;
v_deptno emp.deptno%TYPE;
BEGIN
IF pi_condi IS NOT NULL THEN
v_where := ' WHERE '||pi_condi;
END IF;
v_sql := 'SELECT empno, ename, sal, deptno FROM emp ' ||v_where;
216


OPEN cur_emps FOR v_sql;

LOOP
FETCH cur_emps INTO v_empno, v_ename, v_sal, v_deptno;
EXIT WHEN cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_empno ||' ' || v_ename||' ' ||
v_sal ||' ' || v_deptno);
END LOOP;
CLOSE cur_emps;
END;
/
>CALL list_employees('sal < 3000');
> call list_employees('job = ''MANAGER''')
> call list_employees()

Assignment: Change the above logic and have list_employees returning the cursor to the calling
program instead of printing the records inside the procedure



Ex-5

CREATE OR REPLACE PACKAGE sales AS
PROCEDURE create_sales
(
pi_year VARCHAR2,
pi_month VARCHAR2
);

PROCEDURE drop_sales
(
pi_year VARCHAR2,
pi_month VARCHAR2
);

TYPE cur_ty IS REF CURSOR;
PROCEDURE get_sales
(
pi_year VARCHAR2,
pi_month VARCHAR2,
217

po_cur_sales OUT cur_ty
);
END;
/

CREATE OR REPLACE PACKAGE BODY sales AS
v_sql VARCHAR2(1000);

PROCEDURE create_sales
(
pi_year VARCHAR2,
pi_month VARCHAR2
) IS
BEGIN
v_sql := 'CREATE TABLE sales_'||pi_year||'_'||pi_month
||'(ordno NUMBER(5),
ino NUMBER(5),
qty NUMBER(15)
)';
EXECUTE IMMEDIATE v_sql;
END;

PROCEDURE drop_sales
(
pi_year VARCHAR2,
pi_month VARCHAR2
) IS
BEGIN
v_sql := 'DROP TABLE sales_'||pi_year||'_'||pi_month;
EXECUTE IMMEDIATE v_sql;
END;

PROCEDURE get_sales
(
pi_year VARCHAR2,
pi_month VARCHAR2,
po_cur_sales OUT cur_ty
) IS

BEGIN
v_sql := 'SELECT * FROM sales_'||pi_year||'_'||pi_month;
218

OPEN po_cur_sales FOR v_sql;
END;
END;

In case you get an error of insufficient privileges while executing the create_sales and drop_sales
procedures then do the following –
1. conn sys/sys as sysdba
2. GRANT CREATE TABLE TO <user_name>

Assignment:
1. INSERT 10-15 records into the table created by you
2. Write calling program for get_sales



















219

Object Oriented Concepts
1. Abstraction – hiding of details that are irrelevant is called as an abstraction. One of the good
examples is about the car. User/Driver of the car ignores the details of how engine or any other
mechanical part functions as it is not relevant. But the same details are not ignored by a
mechanic. Oracle supports abstraction in the form of stored PL/SQL program objects.
2. Encapsulation – Grouping of Properties and behavior together is called as Encapsulation.
3. Class – It is a vehicle to implement the Abstraction and Encapsulation. It is a unit that
encapsulates properties and behavior together. In Oracle instead of a class there is an object
type
4. Object – It is an instance of a class. It contains the properties and behavior defined by the class.
These are created at runtime and memory is allocated to store their values
5. Inheritance – Not supported by Oracle
6. Containership – When an object of one class (object type) is declared as a member of another
class (object type) then it is called as containership
Object Type
1. It is a stored schema object
2. It is a collection of member attributes (properties] and member methods [behavior]
3. It is created in two parts
a. Specification – can contain declaration of member attributes and member methods
b. Body – Required only when specification contains the declaration of member methods
4. At runtime instances of this object type is created and they are called as objects
5. Using these objects, you can access the members declared in the specification. Those members
which are part of ONLY BODY and not declared in the specification, cannot be accessed outside
that object type body
6. By default Oracle creates NULL objects unless they are initialized using constructor method
7. Constructor method is the by default method available in Oracle which is having the same
name as an object type. It also accepts same number of parameters as an object type attributes
Syntax
CREATE [OR REPLACE] TYPE <name> AS OBJECT
(
<member attribute1>
[, <member attribute2>]
.
.
.
[,<member method>]
)

220

CREATE OR REPLACE TYPE address_ty AS OBJECT
(
street VARCHAR2(15),
city VARCHAR2(15),
state VARCHAR2(15),
pin VARCHAR2(6)
)
/

DECLARE
v_add1 ADDRESS_TY;
BEGIN
v_add1 := ADDRESS_TY('MG ROAD','MUMBAI','MAHARASHTRA','410210');
DBMS_OUTPUT.PUT_LINE(v_add1.street || ' '||
v_add1.city || ' '||
v_add1.state || ' '||
v_add1.pin);
END;
/

 The following program will result in an error as we are trying to access NULL object attributes
DECLARE
v_add1 ADDRESS_TY;
BEGIN
v_add1.city := 'PUNE';
v_add1 := ADDRESS_TY('MG ROAD','MUMBAI','MAHARASHTRA','410210');
DBMS_OUTPUT.PUT_LINE(v_add1.street || ' '||
v_add1.city || ' '||
v_add1.state || ' '||
v_add1.pin);
END;
/
Once object is initialized, you can access its attributes
DECLARE
v_add1 ADDRESS_TY;
BEGIN
v_add1 := ADDRESS_TY('MG ROAD','MUMBAI','MAHARASHTRA','410210');
DBMS_OUTPUT.PUT_LINE(v_add1.street || ' '||
221

v_add1.city || ' '||
v_add1.state || ' '||
v_add1.pin);
v_add1.city := 'PUNE';
DBMS_OUTPUT.PUT_LINE(v_add1.street || ' '||
v_add1.city || ' '||
v_add1.state || ' '||
v_add1.pin);
END;
/

Storing objects inside table using object column
CREATE TABLE customer
(
cno NUMBER(5),
cname VARCHAR2(25),
address ADDRESS_TY
);

INSERT INTO customer VALUES (1001, 'SACHIN', ADDRESS_TY('SHIVAJI
ROAD','PUNE','MAHARASHTRA','402190'));
INSERT INTO customer VALUES (1002, 'SAURAV', ADDRESS_TY('TAGORE
ROAD','CALCUTTA','BENGAL','302450'));
INSERT INTO customer VALUES (1003, 'RAHUL', ADDRESS_TY('MG
ROAD','BANGLORE','KARNATAKA','205190'));
NOTE: In the above case customer table contains the records that has partial relational data as well as
object data so this table is called as Object Relational Table.
SELECT * FROM customer;  will give you data using constructor method. If you need to get the
data in normal relational format then use the following –
SELECT CNO, CNAME, c.address.street street, c.address.city city, c.address.state state, c.address.pin pin
FROM customer c;

UPDATE customer c
SET c.address.city = 'NAGPUR',
c.address.state = 'MAHARASHTRA',
c.address.pin = '709876'
222

WHERE cno = 1003;

DELETE FROM customer c WHERE c.address.state = 'MAHARASHTRA';
---------------------------------------------------------------------------------------------------------
Dependencies between the objects can be retrieved from user_dependencies.
 Desc user_dependencies;
To find the objects dependent on ADDRESS_TY, following statement can be issued -
SELECT name,type
FROM user_dependencies
WHERE referenced_name = 'ADDRESS_TY';

- When you try to drop these objects using DROP TYPE statement, ORACLE will generate an error
as they have dependencies.
 DROP TYPE address_t y;
- FORCE option can be used to DROP these objects even after having dependencies –
 DROP TYPE address_ty FORCE;
- When FORCE option is used, ORACLE will drop all the columns/attributes from dependent
tables/types before dropping this type
Nested Object Types (Containership)
CREATE OR REPLACE TYPE address_ty AS OBJECT
(
street VARCHAR2(15),
city VARCHAR2(15),
state VARCHAR2(15),
pin VARCHAR2(6)
)
/

CREATE OR REPLACE TYPE person_ty AS OBJECT
(
name VARCHAR2(25),
address ADDRESS_TY
)
/
DECLARE
v_person PERSON_TY;
BEGIN
223

v_person := PERSON_TY('SACHIN',ADDRESS_TY('MG ROAD','MUMBAI','MAHARASHTRA','410210'));
DBMS_OUTPUT.PUT_LINE(v_person.name || ' '||
v_person.address.city || ' '||
v_person.address.state || ' '||
v_person.address.pin);
END;


- Storing objects in the table –
- > CREATE TABLE customer
(
cno NUMBER(5),
person PERSON_TY
);









INSERT INTO customer
VALUES (1001, PERSON_TY('SACHIN',
Customer
person cno
address name
street city state pin
224

ADDRESS_TY('MG ROAD','MUMBAI','MAHARASHTRA','410210')));

INSERT INTO customer
VALUES (1002, PERSON_TY('RAHUL',
ADDRESS_TY('SHIVAJI ROAD','PUNE','MAHARASHTRA','430340')));

INSERT INTO customer
VALUES (1003, PERSON_TY('SAURAV',
ADDRESS_TY('TIGER NAGAR','KOLKATTA','BENGAL','300456')));

- Write a SELECT statement to retrieve cno, name, street, city, state & pin

> SELECT cno, C.person.name name, C.person.address.street street, C.person.address.city city,
C.person.address.state state, C.person.address.pin pin
FROM customer C;
Collector Types
1. There are two collector types
a. VARRAY [VARRYING ARRAYS]
b. NESTED TABLE
2. Objects of these types are called as collections
3. Collection contains multiple elements of same data type. These elements are accessed using
index number or subscript number
4. Collections can store instances (objects) of objects types and they can be members of an object
type

1. VARRAY
- These types are created with a limit. Meaning, total number of elements collection of these
types can contain are fixed
- They have fixed lower bound of 1 and extensible upper bound but not beyond the limit
Syntax
CREATE [OR REPLACE] TYPE <name> AS VARRAY (<limit>) OF <data type / object type> [NOT NULL]
CREATE OR REPLACE TYPE marks_va AS VARRAY(6) OF NUMBER(3)
/



225

DECLARE
v_marks MARKS_VA;
v_total NUMBER := 0;
BEGIN
v_marks := MARKS_VA(75,60,80);
FOR i IN 1..v_marks.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(v_marks(i));
v_total := v_total + v_marks(i);
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Total Marks :' || v_total);
END;
/


- Example to store instances (objects) of an object type
CREATE OR REPLACE TYPE marks_ty AS OBJECT
(
sub_name VARCHAR2(15),
sub_marks NUMBER(3)
)
/

CREATE OR REPLACE TYPE marks_va AS VARRAY(6) OF marks_ty
/








226

DECLARE
v_marks MARKS_VA;
v_total NUMBER := 0;
BEGIN
v_marks := MARKS_VA(MARKS_TY('MATHS',50),MARKS_TY('ENGLISH',60));
FOR i IN 1..v_marks.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE('Subject: ' || v_marks(i).sub_name
|| ' Marks: ' || v_marks(i).sub_marks);
v_total := v_total + v_marks(i).sub_marks;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Total Marks :' || v_total);
END;
/
- Create a table by the name students which has following columns –
Rollno NUMBER(5)
Name VARCHAR2(25)
Marks marks_va
- Insert 3-4 records in this table
CREATE TABLE students
(
rollno NUMBER(5),
name VARCHAR2(25),
marks MARKS_VA
);

INSERT INTO students VALUES(1001,'SACHIN',
MARKS_VA(MARKS_TY('MATHS',90),
MARKS_TY('ENGLISH',80),
MARKS_TY('HINDI',65)));

INSERT INTO students VALUES(1002,'RAHUL',
MARKS_VA(MARKS_TY('MATHS',90),
MARKS_TY('PHYSICS',99),
MARKS_TY('BIO',85)));

- Write a PL/SQL block to display all these above records along with subject name and marks. After
each student record, it should display the total of that student

227

DECLARE
v_total NUMBER := 0;
CURSOR cur_stud IS
SELECT rollno, name, marks FROM students;
BEGIN
FOR stud_row IN cur_stud
LOOP
DBMS_OUTPUT.PUT_LINE (stud_row.rollno ||' '||stud_row.name);
FOR i IN 1..stud_row.marks.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE('Subject: ' || stud_row.marks(i).sub_name
|| ' Marks: ' || stud_row.marks(i).sub_marks);
v_total := v_total + stud_row.marks(i).sub_marks;
END LOOP;
DBMS_OUTPUT.PUT_LINE (' Total Marks :' || v_total);
v_total := 0;
END LOOP;
END;
/
Nested Tables
1. Collections of TABLE type are called as Nested Tables
2. They don’t have any limit
3. They have no fixed lower bound and have extensible upper bound
4. They can be represented as columns of other table
5. Data of nested tables is stored out of line in different storage table
CREATE OR REPLACE TYPE emp_ty AS OBJECT
(
empno NUMBER(5),
ename VARCHAR2(30),
sal NUMBER(5),
job VARCHAR2(20)
)
/

CREATE OR REPLACE TYPE emp_nt AS TABLE OF emp_ty
/




228


CREATE TABLE my_dept
(
deptno NUMBER(2),
dname VARCHAR2(15),
loc VARCHAR2(15),
emps emp_nt
) NESTED TABLE emps STORE AS emp_tab;

- In the above example emp_tab is a storage table that stores data of emps nested table. No DML or
SELECT operations can be performed on emp_tab. These operations must be performed on emps
only.
DESC emp_tab
INSERT INTO my_dept VALUES(10, 'SALES', 'MUMBAI',
EMP_NT(EMP_TY(1001,'SACHIN',7000,'MANAGER'),
EMP_TY(1002,'DHONI',5000,'ANALYST'),
EMP_TY(1005,'NEHRA',2000,'CLERK'),
EMP_TY(1007,'YUVRAJ',5500,'ANALYST')
)
);

INSERT INTO my_dept
VALUES(20, 'MKTG', 'CHENNAI', EMP_NT(EMP_TY(1003,'SAURAV',5000,'MANAGER'),
EMP_TY(1004,'ZAHEER',3000,'SALESMAN')
)
);

INSERT INTO my_dept VALUES(30, 'OPERATIONS', 'KOLKATTA',NULL);
SELECT deptno, dname, loc, e.* FROM my_dept d, TABLE(d.emps) e;
In the above SELECT statement, data of department 30 will not come as, by default Oracle is using
equi-join. So to get that additional record, you can use the following statement –
SELECT deptno, dname, loc, e.* FROM my_dept d, TABLE(d.emps)(+) e;
- Please SELECT all emps working in dept =10

SELECT * FROM TABLE (SELECT emps FROM my_dept WHERE deptno=10)

- Please SELECT record of only SACHIN
229


SELECT * FROM TABLE (SELECT emps FROM my_dept WHERE deptno=10)
WHERE ename='SACHIN';
- Change job of SACHIN to SR. MANAGER and salary to 9000

UPDATE TABLE (SELECT emps FROM my_dept WHERE deptno=10)
SET sal = 9000,
job = 'SR. MANAGER'
WHERE ename='SACHIN'
/

- DELETE record of SACHIN
DELETE FROM TABLE (SELECT emps FROM my_dept WHERE deptno=10) WHERE
ename='SACHIN';

- You can copy a set of data from one parent record into another as below –
INSERT INTO my_dept
VALUES(40,'HR','MUMBAI',
CAST(MULTISET(SELECT * FROM TABLE (SELECT emps
FROM my_dept WHERE deptno=10
)
)AS EMP_NT)
);

CAST operator allows to convert the output of the SELECT statement to the COLLECTION of
COLLECTOR TYPE.
MULTISET operator allows CAST query to contain more than one records.

- You can apply constraints to the nested table –
CREATE TABLE my_dept
(
deptno NUMBER(2),
dname VARCHAR2(15),
loc VARCHAR2(15),
emps emp_nt
) NESTED TABLE emps STORE AS emp_tab
(
(
CONSTRAINT pk_emps_empno PRIMARY KEY (empno),
CONSTRAINT chk_emps_sal CHECK (sal IS NOT NULL AND sal > 1000),
CONSTRAINT chk_emps_ename CHECK (ename = UPPER(ename))
230

)
);



Assignment: Create a table order_master which will have the following columns –
Ordno NUMBER(5)
Odate DATE
Items items_nt

Items must be a nested table having ino, qty and price columns

The following constraint must be added –
1. ORDNO must be a PRIMARY KEY
2. Odate MUST be not NULL
3. Identify the primary key for items table (ino alone can’t be primary key)
4. Qty should be greater than 0
5. Price should be NOT NULL
Collector Methods
1. These are pre-defines functions or procedures which can be used only inside PL/SQL block
2. They can be invoked using collection (<collection>.<method_name>)
The following are the methods
1. EXISTS (<n>) - It returns TRUE if nth element exists else returns FALSE
2. FIRST
a. It returns an index number of the first element of the given collection
b. For VARRAY collection it will be always 1, but for nested table it may be greater than 1 if
elements are deleted in the beginning
3. LAST – It returns an index number of the last element of the given collection
4. COUNT
a. It returns the total number of elements collection currently contains
b. Value of COUNT may be less than LAST if elements are deleted from the given collection
5. PRIOR (<n>)
a. It returns an index number of an element that precedes given nth element
b. Returns NULL if there is no element that precedes given nth element
6. NEXT (<n>)
a. It returns an index number of an element that succeeds given nth element
b. Returns NULL if there is no element that succeeds given nth element
7. EXTEND
231

a. It is used to append elements to the collection
b. EXTEND - It appends one NULL element to the given collection
c. EXTEND(<n>) – It appends n number of NULL elements to the given collection
d. EXTEND (<n>, <i>) – It appends n copies of ith element to the given collection
8. LIMIT – It returns the total number of elements that collection of VARRAY can contain
9. DELETE
a. It is used to DELETE all of specific elements from the given collection
b. DELETE keeps the place holders
c. DELETE – All elements will be deleted
d. DELETE(<n>) – nth element from collection of nested table will be deleted
e. DELETE (<m>,<n>) – It deletes elements between mth to nth from the collection of
nested table
10. TRIM
a. It removes the elements from the end of the collection
b. It does not keep place holders
c. TRIM – Removes one element
d. TRIM (<n>) – It removes n number of elements from the collection
BULK Binding
1. Assigning of values to/from PL/SQL variables is called as binding
2. When collections are used, instead of binding individual elements, you can bind entire
collection at once
3. This will help to reduce the context switches between database engine and PLSQL engine and
improve the performance
For an example – depts Is a collection as below -
Depts
50
30
40
20
10

FOR I IN depts.FIRST..depts.LAST
LOOP
DELETE FROM emp WHERE deptno = depts.(i);
END LOOP;

As mentioned above, using FOR LOOP, each element is bound and hence there will be 5 number of
context switches between database engine and pl/sql engine
232

To avoid this you can use FORALL statement as below which will help in binding entire collection at
once
FORALL I IN depts.FIRST..depts.LAST
DELETE FROM emp WHERE deptno = depts.(i);
FORALL
1. It is used to bulk bind the collection which is used inside the DML statement
2. Though entire collection is bound, DML statements will be still executed once for every element
inside the collection
3. In above case, all 5 elements are bound at once, but still DELETE statement will be executed 5
times i.e. once for every element
4. You can bulk bind the elements in the given range if not entire collection
a. Assuming depts Has 1000 elements, instead of binding all 1000 elements, only 200+
elements are bound. Please see below
FORALL i IN 300..500
DELETE FROM emp WHERE deptno = depts.(i);
Example to show the time difference -
CREATE TABLE parts
(
pno NUMBER(10),
pname VARCHAR2(100)
);

DECLARE
TYPE numtab IS TABLE OF NUMBER(10) INDEX BY BINARY_INTEGER;
TYPE nametab IS TABLE OF VARCHAR2(50) INDEX BY BINARY_INTEGER;
pnos numtab;
pnames nametab;
t1 CHAR(5);
t2 CHAR(5);
t3 CHAR(5);

PROCEDURE get_time (t OUT NUMBER) IS
BEGIN
SELECT TO_CHAR(SYSDATE,'SSSSS') INTO t from DUAL;
END;

BEGIN
233

-- creating a collection
FOR i IN 1..100000
LOOP
pnos(i) := i;
pnames(i) := 'Part ' || i;
END LOOP;

-- Storing the current time in T1 and then using FOR LOOP to INSERT values into parts table
-- Context switches will be more as entire collection is not bound
get_time(t1);
FOR i IN 1..pnos.COUNT
LOOP
INSERT INTO parts VALUES(pnos(i), pnames(i));
END LOOP;
get_time(t2);
-- t2 - t1 will give the total time taken to INSERT 50000 records without bulk binding
-- Now using FORALL
FORALL i IN 1..pnos.COUNT
INSERT INTO parts VALUES(pnos(i), pnames(i));
get_time(t3);
-- t3 - t2 will give the total time taken to INSERT 50000 records with bulk binding
DBMS_OUTPUT.PUT_LINE('Without Bulk Binding : ' ||TO_CHAR(t2-t1));
DBMS_OUTPUT.PUT_LINE('With Bulk Binding : ' ||TO_CHAR(t3-t2));
END;
/

BULK_ROWCOUNT
1. It is a cursor attribute which can be used when bulk binding is used (FORALL)
2. It is like a collection which has multiple elements. Total no of elements are determined by the
number of times DML statement given in FORALL is executed
3. It stores the no of records manipulated by DML statement as value of each element
DECLARE
TYPE numtab IS TABLE OF NUMBER(2);
depts numtab := numtab(40,30,20,10);
BEGIN
FORALL i IN 1..depts.COUNT
DELETE FROM emp WHERE deptno = depts(i);

-- Checking total number of records deleted by each execution of DELETE
234

-- To do this you can use BULK_ROWCOUNT
FOR i IN 1..depts.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(i || ' Execution has Deleted ' || SQL%BULK_ROWCOUNT(i)
|| ' Records');
END LOOP;
END;
/




The following example shows the dependencies amongst the executions –
DECLARE
TYPE numtab IS TABLE OF NUMBER(2);
depts numtab := numtab(40,30,20,10);
BEGIN
depts.DELETE(3);
FORALL i IN 1..depts.COUNT
DELETE FROM emp WHERE deptno = depts(i);
END;
/

As specified above, 1
st
and 2
nd
execution of DELETE is successful but 3
rd
will result in an error as
element does not exists. If you handle this in an exception then Oracle will allow you to commit those
changes done by first two executions.
DECLARE
TYPE numtab IS TABLE OF NUMBER(2);
depts numtab := numtab(40,30,20,10);
BEGIN
depts.DELETE(3);
FORALL i IN 1..depts.COUNT
DELETE FROM emp WHERE deptno = depts(i);

EXCEPTION
WHEN others THEN
COMMIT;
END;
/

235

Using BULK COLLECT clause
1. This clause can be used to bulk bind the values from database engine to pl/sql engine
2. It can be used in SELECT, FETCH and RETURNING clause
3. Using this you can BULK fetch the values into collections



Example with SELECT statement
DECLARE
TYPE empnotab IS TABLE OF emp.empno%TYPE;
TYPE enametab IS TABLE OF emp.ename%TYPE;
TYPE saltab IS TABLE OF emp.sal%TYPE;
empnos empnotab;
enames enametab;
sals saltab;
BEGIN
SELECT empno, ename, sal
BULK COLLECT INTO empnos, enames, sals
FROM emp;
FOR i IN 1..empnos.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(empnos(i) ||' '|| enames(i) ||' ' ||sals(i) );
END LOOP;
END;
/
Example with FETCH
DECLARE
TYPE empnotab IS TABLE OF emp.empno%TYPE;
TYPE enametab IS TABLE OF emp.ename%TYPE;
TYPE saltab IS TABLE OF emp.sal%TYPE;
empnos empnotab;
enames enametab;
sals saltab;
CURSOR c1 IS
SELECT empno, ename, sal FROM emp;
BEGIN
OPEN c1;
236

FETCH c1 BULK COLLECT INTO empnos, enames, sals;
CLOSE c1;

FOR i IN 1..empnos.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(empnos(i) ||' '|| enames(i) ||' ' ||sals(i) );
END LOOP;

END;
/

Example with RETURNING
DECLARE
TYPE empnotab IS TABLE OF emp.empno%TYPE;
TYPE enametab IS TABLE OF emp.ename%TYPE;
TYPE saltab IS TABLE OF emp.sal%TYPE;
empnos empnotab;
enames enametab;
sals saltab;
BEGIN

DELETE FROM emp
WHERE deptno = &deptno
RETURNING empno, ename, sal BULK COLLECT INTO empnos, enames, sals;

DBMS_OUTPUT.PUT_LINE(' Following employees are deleted');
FOR i IN 1..empnos.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(empnos(i) ||' '|| enames(i) ||' ' ||sals(i) );
END LOOP;

END;
/

Using FORALL and BULK COLLECT together
DECLARE
TYPE numtab IS TABLE OF NUMBER(2);
depts numtab := numtab(40,30,20,10);
TYPE empnotab IS TABLE OF emp.empno%TYPE;
237

TYPE enametab IS TABLE OF emp.ename%TYPE;
TYPE saltab IS TABLE OF emp.sal%TYPE;
empnos empnotab;
enames enametab;
sals saltab;

BEGIN
FORALL i IN 1..depts.COUNT
DELETE FROM emp WHERE deptno = depts(i)
RETURNING empno, ename, sal BULK COLLECT INTO empnos, enames, sals;

DBMS_OUTPUT.PUT_LINE(' Following employees are deleted');
FOR i IN 1..empnos.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(empnos(i) ||' '|| enames(i) ||' ' ||sals(i) );
END LOOP;
END;
/

Example with %ROWTYPE
DECLARE
TYPE numtab IS TABLE OF NUMBER(2);
depts numtab := numtab(40,30,20,10);
TYPE emptab IS TABLE OF emp%ROWTYPE;
emps emptab;
BEGIN
FORALL i IN 1..depts.COUNT
DELETE FROM emp WHERE deptno = depts(i)
RETURNING empno,ename,job, mgr, hiredate,sal,comm,deptno
BULK COLLECT INTO emps;

DBMS_OUTPUT.PUT_LINE(' Following employees are deleted');
FOR i IN 1..emps.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(emps(i).empno||' '|| emps(i).ename ||' ' ||emps(i).sal);
END LOOP;
END;
/

238

DECLARE
CURSOR c1 IS
SELECT * FROM emp;
TYPE emptab IS TABLE OF emp%ROWTYPE;
emps emptab;
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO emps;
CLOSE c1;
FOR i IN 1..emps.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(emps(i).empno||' '|| emps(i).ename ||' ' ||emps(i).sal);
END LOOP;
END;
/


























239

Database Internal Concept
• Oracle Database Structure
• Memory Architecture
• Processes
• Roles and Privileges
• Oracle Parallel Server configuration
• Distributed Database Configuration




240



241



242



243



244



245



246



247



248


249



250



251



252




253


254



255


















256

Roles and Privileges
Privileges: There are two types of privileges –
1. System Privileges
2. Object Privileges
System Privileges
1. There are over 60 system privileges
2. They allow user to perform a specific database operation
3. Oracle manual says that these system privileges are very powerful and MUST BE
cautiously granted to trusted users, roles
To create the users following statement can be used –

CREATE USER sachin IDENTIFIED BY tiger
DEFAULT TABLESPACE accounts
TEMPORARY TABLESPACE temp;
To grant the privileges GRANT statement used and to revoke REVOKE statement is used –
Syntax
GRANT <privilege(s)> TO <user_name(s)>
- With single GRANT statement you can GRANT one or many system privileges to one or
many users, roles
- System privileges and roles can be granted together with single grant statement
-
GRANT create session TO sachin WITH ADMIN OPTION;
WITH ADMIN OPTION:
If any system privilege is granted WITH ADMIN OPTION, then grantee can further grant
that system privilege to other users.





257

ROLE:
1. Role is a collection of privileges and other roles
2. Privileges can be granted to roles, Roles can be granted to other roles as well as
users.
3. To create the role, you must have CREATE ROLE system privileges
4. To drop the role, you must have DROP ROLE system privileges
There can be two types of roles
1. Pre defined role
2. User defined role
Few important Pre defined roles:
Connect, resource, DBA, etc……
Example:-
GRANT DBA TO user;
CREATE ROLE r1;
GRANT create session, create table, create procedure TO r1;
GRANT r1 TO sachin;
Object Privileges
1. They are specific to a particular object
2. They can be granted by the owner or the user who has received these WITH GRANT
OPTION
3. They cannot be granted together with system privileges and roles with a single GRANT
statement. You have to use separate GRANT statement
Privilege Table View Sequence Procedure/
Function/
Package
Snapshot
INSERT YES YES NO NO NO
UPDATE YES YES NO NO NO
DELETE YES YES NO NO NO
SELECT YES YES YES NO YES
EXECUTE NO NO NO YES NO
ALTER YES YES YES YES NO
REFERENCES YES NO NO NO NO
INDEX YES NO NO NO NO

258

4. ALL keyword can be used in GRANT statement to grant all the privileges that are
applicable to that object
GRANT ALL ON emp TO Hr;
GRANT insert, update, delete ON dept To hr WITH GRANT OPTION;
- In the above case HR user has received privileges WITH GRANT OPTION, so HR can
further GRANT these privileges to other users
WHEN you GRANT the privileges, they are appended to the list of existing privileges and not
overwritten
So now if I want HR to have an access to only UPDATE values of sal column, I need to first
revoke an UPDATE privilege and then GRANT UPDATE (sal)
REVOKE update on emp FROM hr;
GRANT UPDATE(sal) ON emp TO hr;
Synonyms
They are schema objects which can be used as reference name to refer objects from remote
databases as well from other schemas
Syntax
CREATE [PUBLIC] SYNONYM <name> FOR <source>
Ex
CREATE SYNONYM emp FOR sachin.emp;
CREATE SYNONYM sales_tran FOR sales_tran@sales;
PUBLIC keyword can be used so that it can be accessed by all users in that database

259


DISTRIBUTED DATABASE SYSTEM
CREATE DATABASE LINK <name>
CONNECT TO <usersname> IDENTIFIED BY <password>
USING '<hoststring>'

For Eg:
You have the database by the name Sales which has Table:sales_trans as well as other
objects. So to access them create the following Database Link.

CREATE DATABASE LINK sales
CONNECT TO sachin IDENTIFIED BY tiger
USING 'INDIA'
Now to access the objects stored in sachin schema you can use the following syntax :-
1. SELECT * FROM sales_tran@sales;
2. INSERT into Sales_tran@sales(<column_name>) VALUES (<values>)
3. Exec P1@sales(<parameter name>)

SnapShot:- It is a schema object created in the local database which contains the data of the
remote database object. The snapshot can be scheduled to be refreshed at specific time
intervals for Eg:
In the Marketing database I am creating a snapshot as SNP_ST which will store the database
of sales_tran table from sales database, to do the same you need to use the Database Link.
CREATE SNAPSHOT snp_st
REFRESH START WITH SYSDATE
NEXT NEXT_DAY(SYSDATE,'MONDAY') AS
SELECT * FROM sales_tran@sales
-----------------------------------------------------------------------------------
260

Clusters
1. It is a collection of tables
2. Data of multiple tables (having common cluster key) can be stored together in a single
data segment by using clusters
3. This helps to save disk space as well as improve the performance of joins
4. Each data block stores the cluster key value and data from all the tables having same
value of cluster key together in same data block
CREATE CLUSTER cl_dept_emp
(
deptno NUMBER(2)
);

CREATE TABLE my_dept
(
deptno NUMBER(2) PRIMARY KEY,
dname VARCHAR2(15),
loc VARCHAR2(15)
) CLUSTER cl_dept_emp (deptno);

CREATE TABLE my_emp
(
empno NUMBER(5) PRIMARY KEY,
ename VARCHAR2(50),
sal NUMBER(5),
deptno NUMBER(2) REFERENCES my_dept
) CLUSTER cl_dept_emp (deptno);
If cluster is empty then it can be dropped by using – DROP CLUSTER cl_dept_emp but if it
contains tables then you have to use – INCLUDING TABLES clause. In case one of the tables of
this cluster has a parent key that is referred by the foreign key of the table which is not the
part of this cluster, you have to use CASCADE CONSTRAINTS clause
261

TEMPORARY TABLES:
 In Oracle, there is a feature of global temporary tables (So called as Temporary Tables).
There are two types of Temporary Tables
1. Transaction Specific Temporary Tables
2. Session Specific Temporary Tables

 Structure of the table is permanent like a normal table, but rows (data) are temporary.
 Oracle uses temporary segment to store the data of temporary tables
 Alter and Drop operations can be perform only when no session is bound to it
 Session get bound after issuing an insert statement
 Data store in the temporary table is private to the session and stored in the separate temporary
segment for every session
 Data is removed for Transaction Specific Temporary Table when commit or rollback or truncate
is issued or session is closed, but for Session Specific Temporary Table data is removed when
the session is closed or truncate issues
USE OF TEMPORARY TABLES:
 Temporary tables are used for improving the performance of PL/SQL code or for generating the
reports

To create temporary table: (Session Specific Temporary Tables)
CREATE GLOBAL TEMPORARY TABLE t_emp
(
empno NUMBER(5),
ename VARCHAR2(25),
sal NUMBER(5)
) ON COMMIT PRESERVE ROWS
/

To insert data into the table:
INSERT INTO t_emp VALUES (1001,’ANIL’, 5600);
SQL> SELECT * FROM t_emp;
EMPNO ENAME SAL
---------- ------------------------- ----------
1001 ANIL 5600
Open another session with same user:
262

 SELECT * FROM t_emp;
No rows selected
DROP TABLE t_emp;

To create temporary table: (Transaction Specific Temporary Tables)
CREATE GLOBAL TEMPORARY TABLE t_emp
(
empno NUMBER(5),
ename VARCHAR2(25),
sal NUMBER(5)
) ON COMMIT DELETE ROWS
/
INSERT INTO t_emp VALUES (1001,’ANIL’, 5600);
SQL> SELECT * FROM t_emp;
EMPNO ENAME SAL
---------- ------------------------- ----------
1001 ANIL 5600
COMMIT;
 SELECT * FROM t_emp;
No rows selected
MATERIALIZED VIEW:
 Materialized view is a schema object consumes the disk space
The following are the areas for real time use of materialized vies
1) DWH applications(Decision Support System)

 In this case aggregate data of historical tables can be stored in the materialized views, so that
you don’t need to write the queries on historical tables again and again
 In state these queries are written against materialized view
 Materialized view can be said to refresh at the periodic interval

2) Distributed Database System

 In this case it can be used as a replacement to the snapshot
 Snap shot is read only where as materialized view is writeable
263


3) Mobile Computing
 In mobile computing, it is used to get the data from centralized database into local database of
laptop, mobile, etc. As well as changes made to the materialized view, data can be refreshed back to
the centralized server




Example of MV
CREATE MATERIALIZED VIEW mv_emp
REFRESH START WITH SYSDATE
NEXT NEXT_DAY(SYSDATE,'MONDAY')
AS
SELECT e.deptno,dname,loc,sum(sal) sum_sal,avg(sal) avg_sal, max(sal) max_sal,min(sal) min_sal
FROM emp e,dept d
WHERE e.deptno=d.deptno
GROUP BY e.deptno,dname,loc
/

SELECT * FROM mv_emp;
Pseudo Columns
1) Uid(user id) : It will give you the id given by oracle to that user
SELECT uid FROM DUAL;
2) USER : It will give you the name of the user
SELECT user FROM DUAL;
3) Rowid : It will give the address of particular row address
SELECT ename,rowed FROM emp;
4) Rownum : It will give you the running serial number of that record
SELECT rownum,ename FROM emp;





264

LIST OF PREDEFINED PACKAGES
1) UTL_FILE :
 It is used for input, output operations from/to the flat files
 It contains the procedures and functions that are used to generate write to the flat file (or) read
to the flat file
 It is used widely for interface programming

2) DBMS_JOBS : It is used to schedule the process
3) DBMS_PIPE : It is used to communicate between the sessions , not widely used
4) DBMS_LOB : It is used to perform read/write operations to perform on large objects
5) DBMS_SQL : It is used to execute dynamic sequel statements
6) DBMS_OUTPUT : It is used to show the output of PL/SQL block
7) UTL_MAIL : It is used to perform email operations
8) OWA_UTIL : The OWA_UTIL package contains utility subprograms for performing operations
such as getting the value of CGI environment variables, printing the data that is returned to the
client, and printing the results of a query in an HTML table
INDEX ORGANIZED TABLE:
1) In this case entire data of the table is stored in an index segment
2) This table must have a primary key
3) Rows of this table are accessed by using primary key
4) You can not create indexes on any of the columns of this table


CREATE TABLE emp
(
Empno NUMBER(5) PRIMARY KEY,
Ename VARCHAR(25),
Sal NUMBER(5)
) ORGANIZATION INDEX
/






265

NO COPY Compiler hint:
No copy compiler hint is very important with respect to improving the performance
Incase of IN mode, formal parameter and actual parameter both share the same memory location i.e.,
when actual parameter data is not copied ,but incase of OUT and IN OUT value of formal parameter
copied to the formal parameter and then when program exit, values of formal parameter is copied into
actual parameter
All this coping takes time and impacts the performance if the program
Generally NO COPY should be used when you are passing collections or big objects as a parameters.
DECLARE
TYPE EmpTabTyp IS TABLE OF emp%ROWTYPE;
emp_tab EmpTabTyp := EmpTabTyp(NULL); -- initialize
t1 NUMBER(5);
t2 NUMBER(5);
t3 NUMBER(5);

PROCEDURE get_time (t OUT NUMBER) IS
BEGIN
SELECT TO_CHAR(SYSDATE,'SSSSS') INTO t FROM dual;
END;

PROCEDURE do_nothing1 (tab IN OUT EmpTabTyp) IS
BEGIN
NULL;
END;

PROCEDURE do_nothing2 (tab IN OUT NOCOPY EmpTabTyp) IS
BEGIN
NULL;
END;

BEGIN
SELECT * INTO emp_tab(1) FROM emp WHERE empno = 7788;
emp_tab.EXTEND(24999, 1); -- copy element 1 into 2..25000

get_time(t1);
do_nothing1(emp_tab); -- pass IN OUT parameter

get_time(t2);
do_nothing2(emp_tab); -- pass IN OUT NOCOPY parameter
get_time(t3);

dbms_output.put_line('Call Duration (secs)');
266

dbms_output.put_line('--------------------');
dbms_output.put_line('Just IN OUT: ' || TO_CHAR(t2 - t1));
dbms_output.put_line('With NOCOPY: ' || TO_CHAR(t3 - t2));

END;
/



BITMAP INDEX :
A. Employee Table
Rowid Empno Ename Sal Deptno
F001 1001 A 4000 20
F002 1002 B 5000 10
F003 1003 C 7720 10
F004 1004 D 8522 20
F005 1005 E 2222 10

B. Binary Search Index C. BITMAP Index
Deptno Rowid
10 F002
10 F003
10 F005
20 F001
20 F004


1. When you create the Bitmap index Oracle stores unique values of the index keys as the
columns and for every record it stores either one or zero in that corresponding columns based
on the value of the column which has bitmap index. As written above (A) one will be stored for
the records which has that corresponding column value and for rest of the columns it will store
zero.
2. When the filter condition are used on the Indexed columns Oracle will load the Index segment
into the database buffer cache and filter all those records whose bits are ON i.e 1 of that
corresponding column value, applies a map function to convert that bit to the corresponding
Rowid and gets only those records from the data segment.
3. Oracle Corporation recommends you to create bitmap index only on the columns which has
large amount of duplicate values. Also create bitmap indexes only on those columns which are
not modified frequently.

10 20 30
0 1 0
1 0 0
1 0 0
0 1 0
1 0 0
267

SDLC Stages
1. Plan
2. Define
3. Design
4. Build
5. Test
6. Install & Acceptance
Phase Resources Involved Out put
Plan Project Manager, Account
Manager, Program Manager
High Level Project plan with milestones, WBS, Detailed
level project plan etc.
Define Users, BA, Domain Experts FRS, SRS, Use Cases, Approach Document, GAP
document
Design Functional experts, technical
experts, designers, PL, ML
HLD, LLD, Working prototypes, Test scenarios
Build PL, ML, Developers Source code, Unit test results
Test Testers, Test Leads, PL, ML,
Developers
Certified source code, System test cases and results. QC
certification to release the code on UAT.
Install DBA, CIC UAT env.
Acceptance User Accepted code and User acceptance cases and results.
Finally user acceptance to go live.

PERFORMANCE TUNING

1. Performance tuning can be done at three levels
a. Database level
b. Code level
c. Hardware configuration level
Out of the above levels Code level tuning can be done at developer level, even in the code level
tuning the tuning can be done at front end code as well as back end code.
Tuning the code can be done at three stages :
1.1. Identification
1.2. Analysis and Design
1.3. Fix

1.1. Identification – At this stage you have to identify the code that requires tuning and fix.
To do so you can use following techniques :-
1.1.1. Find out the queries that are taking time or in other words costly queries that are
using maximum hardware and database resources. This can be done by running a select
statement on the data dictionary tables.
1.1.2. User of AWR report – By using this report you can find out the code and queries that
are having problem.
1.1.3. Use of TKPROF utility (Refer Slide for details)

2. Analysis and Design :-
268


2.1. Once code / query for tuning is identified you have to find out the most efficient way to
tune the code. At this stage you may have to use Explain plan statement to get the execution
plan for further analysis and changes, and if required you have to redesign the code or queries.

2.2. To understand the Execution plan for the given SQL statement you have to use Explain
Plan Statement.

2.3. Explain Plan Statement will store the Execution plan of the given SQL statement into the
table ‘PLAN_TABLE’.

2.4. ‘PLAN_TABLE’ must be created into you schema and to do so you have to use
UTLXPLAN.sql script.

2.5. Oracle Optimizer is responsible for selection of most efficient execution plan for the
given statement.

2.6. There are two methods of optimization
2.6.1. Cost based optimization
2.6.2. Rule based optimization
In the current version of Oracle, Rule based optimization is not supported and Oracle uses only
Cost based optimization.
2.6.2.1. Cost Based Optimizer chooses the most efficient execution plan based on the
cost of that plan. Cost is calculated based on the Statistics of the objects referred in
that SQL statement. These statistics are stored in the Data dictionary tables and they
can be generated either by using ANALYZE statement or by using DBMS_STATS
package. Generally on the production environment objects are analyzed either every
week or bi-weekly basis.

3. Fixing – while fixing you have to consider following points.

3.1. In case of joins identify driving table which has less number of rows. This reduces the
time taken for the join. Driving table is the one which is mention in the end of the from clause.

3.2. While writing the queries follow the coding standards accurately so that there will be
uniformed way to write the same statements. This will help to use the same shared SQL area.

3.3. User temporary tables wherever necessary.

3.4. User BULK BINDING (FOR ALL/BULK COLLECT)

269

3.5. Use NO COPY Compiler HINT

3.6. When there are multiple conditions in where clauses specify that condition in last which
filters maximum numbers of rows.













Normalization is the process of efficiently organizing data in a database. There are two goals of the
normalization process: eliminating redundant data (for example, storing the same data in more than one
table) and ensuring data dependencies make sense (only storing related data in a table). Both of these are
worthy goals as they reduce the amount of space a database consumes and ensure that data is logically
stored.
The Normal Forms
The database community has developed a series of guidelines for ensuring that databases are
normalized. These are referred to as normal forms and are numbered from one (the lowest form of
normalization, referred to as first normal form or 1NF) through five (fifth normal form or 5NF). In
practical applications, you'll often see 1NF, 2NF, and 3NF along with the occasional 4NF. Fifth normal
form is very rarely seen and won't be discussed in this article.
First Normal Form (1NF) sets the very basic rules for an organized database:
 Eliminate duplicative columns from the same table.
 Create separate tables for each group of related data and identify each row with a unique column
(the primary key).
What do these rules mean when contemplating the practical design of a database? It's actually quite
simple.
The first rule dictates that we must not duplicate data within the same row of a table. Within the
database community, this concept is referred to as the atomicity of a table. Tables that comply with this
rule are said to be atomic. Let's explore this principle with a classic example - a table within a human
resources database that stores the manager-subordinate relationship. For the purposes of our example,
270

we'll impose the business rule that each manager may have one or more subordinates while each
subordinate may have only one manager.
Intuitively, when creating a list or spreadsheet to track this information, we might create a table with the
following fields:
 Manager
 Subordinate1
 Subordinate2
 Subordinate3
 Subordinate4
However, recall the first rule imposed by 1NF: eliminate duplicative columns from the same table.
Clearly, the Subordinate1-Subordinate4 columns are duplicative. Take a moment and ponder the
problems raised by this scenario. If a manager only has one subordinate - the Subordinate2-Subordinate4
columns are simply wasted storage space (a precious database commodity). Furthermore, imagine the
case where a manager already has 4 subordinates - what happens if she takes on another employee? The
whole table structure would require modification.
At this point, a second bright idea usually occurs to database novices: We don't want to have more than
one column and we want to allow for a flexible amount of data storage. Let's try something like this:
 Manager
 Subordinates
Where the Subordinates field contains multiple entries in the form "Mary, Bill, Joe"
This solution is closer, but it also falls short of the mark. The subordinates column is still duplicative and
non-atomic. What happens when we need to add or remove a subordinate? We need to read and write
the entire contents of the table. That's not a big deal in this situation, but what if one manager had one
hundred employees? Also, it complicates the process of selecting data from the database in future
queries.
Here's a table that satisfies the first rule of 1NF:
 Manager
 Subordinate
In this case, each subordinate has a single entry, but managers may have multiple entries.
Now, what about the second rule: identify each row with a unique column or set of columns (the
primary key)? You might take a look at the table above and suggest the use of the subordinate column as
a primary key. In fact, the subordinate column is a good candidate for a primary key due to the fact that
our business rules specified that each subordinate may have only one manager. However, the data that
we've chosen to store in our table makes this a less than ideal solution. What happens if we hire another
employee named Jim? How do we store his manager-subordinate relationship in the database?
It's best to use a truly unique identifier (such as an employee ID) as a primary key. Our final table would
look like this:
271

 Manager ID
 Subordinate ID
2
ND
Normal Form
Over the past month, we've looked at several aspects of normalizing a database table. First, we discussed
the basic principles of database normalization. Last time, we explored the basic requirements laid down
by the first normal form (1NF). Now, let's continue our journey and cover the principles of second
normal form (2NF).

Recall the general requirements of 2NF:
 Remove subsets of data that apply to multiple rows of a table and place them in separate tables.
 Create relationships between these new tables and their predecessors through the use of foreign
keys.
These rules can be summarized in a simple statement: 2NF attempts to reduce the amount of redundant
data in a table by extracting it, placing it in new table(s) and creating relationships between those tables.

Let's look at an example. Imagine an online store that maintains customer information in a database.
They might have a single table called Customers with the following elements:
 CustNum
 FirstName
 LastName
 Address
 City
 State
 ZIP
A brief look at this table reveals a small amount of redundant data. We're storing the "Sea Cliff, NY
11579" and "Miami, FL 33157" entries twice each. Now, that might not seem like too much added
storage in our simple example, but imagine the wasted space if we had thousands of rows in our table.
Additionally, if the ZIP code for Sea Cliff were to change, we'd need to make that change in many
places throughout the database.

In a 2NF-compliant database structure, this redundant information is extracted and stored in a separate
table. Our new table (let's call it ZIPs) might have the following fields:
 ZIP
 City
 State
If we want to be super-efficient, we can even fill this table in advance -- the post office provides a
directory of all valid ZIP codes and their city/state relationships. Surely, you've encountered a situation
where this type of database was utilized. Someone taking an order might have asked you for your ZIP
code first and then knew the city and state you were calling from. This type of arrangement reduces
operator error and increases efficiency.

Now that we've removed the duplicative data from the Customers table, we've satisfied the first rule of
272

second normal form. We still need to use a foreign key to tie the two tables together. We'll use the ZIP
code (the primary key from the ZIPs table) to create that relationship. Here's our new Customers table:
 CustNum
 FirstName
 LastName
 Address
 ZIP
We've now minimized the amount of redundant information stored within the database and our structure
is in second normal form!
3
RD
Normal Form
There are two basic requirements for a database to be in third normal form:
 Already meet the requirements of both 1NF and 2NF
 Remove columns that are not fully dependent upon the primary key.
Imagine that we have a table of widget orders that contains the following attributes:
 Order Number
 Customer Number
 Unit Price
 Quantity
 Total
Remember, our first requirement is that the table must satisfy the requirements of 1NF and 2NF. Are
there any duplicative columns? No. Do we have a primary key? Yes, the order number. Therefore, we
satisfy the requirements of 1NF. Are there any subsets of data that apply to multiple rows? No, so we
also satisfy the requirements of 2NF.
Now, are all of the columns fully dependent upon the primary key? The customer number varies with
the order number and it doesn't appear to depend upon any of the other fields. What about the unit price?
This field could be dependent upon the customer number in a situation where we charged each customer
a set price. However, looking at the data above, it appears we sometimes charge the same customer
different prices. Therefore, the unit price is fully dependent upon the order number. The quantity of
items also varies from order to order, so we're OK there.
What about the total? It looks like we might be in trouble here. The total can be derived by multiplying
the unit price by the quantity, therefore it's not fully dependent upon the primary key. We must remove
it from the table to comply with the third normal form. Perhaps we use the following attributes:
 Order Number
 Customer Number
 Unit Price
 Quantity
273

Now our table is in 3NF. But, you might ask, what about the total? This is a derived field and it's best
not to store it in the database at all. We can simply compute it "on the fly" when performing
database queries. For example, we might have previously used this query to retrieve order numbers and
totals :
SELECT OrderNumber, Total
FROM WidgetOrders
We can now use the following query:
SELECT OrderNumber, UnitPrice * Quantity AS Total
FROM WidgetOrders
to achieve the same results without violating normalization rules.

Before we begin our discussion of the normal forms, it's important to point out that they are guidelines
and guidelines only. Occasionally, it becomes necessary to stray from them to meet practical business
requirements. However, when variations take place, it's extremely important to evaluate any possible
ramifications they could have on your system and account for possible inconsistencies
Ex. Normalize the below
ORDNO
ORDDATE
CUSTNO
CUSTNAME
CADD1
CCITY
CSTATE
CPIN
SUPNO
SUPNAME
SADD1
SCITY
SSTATE
SPIN
ITEMNO
ITEMNAME
QTY
PRICE
TOTAL
GRANDTOTAL

274

ADDITIONAL POINTS :
1. Normailzation is a process which is used to design the database. It helps to reduce the data
redundancy by keeping data integrity.
2. Normalization is a set of guidelines which can be followed to normalize the relations stored in the
database
3. There are 3 normal forms with guidelines which are used to normalize the database design.
4. Most complex to complex database designs can be normalized by using these guidelines of 3
normal forms. But still if more normalization is required 4NF and 5NF can be used.


Sponsor Documents

Or use your account on DocShare.tips

Hide

Forgot your password?

Or register your new account on DocShare.tips

Hide

Lost your password? Please enter your email address. You will receive a link to create a new password.

Back to log-in

Close