Dbms Lab Front Pages
Dbms Lab Front Pages
LABORATORY MANUAL
For
Prepared by
CERTIFICATE
Program : B.Tech
Year : II Year
Semester : II Semester
2 Queries (along with sub Queries) using ANY, ALL, IN, EXISTS, 16 - 21 CO1
NOTEXISTS, UNION,
INTERSET, Constraints.
11 Develop Programs using BEFORE and AFTER Triggers, Row 68-69 CO4
and Statement Triggers and
INSTEAD OF Triggers
12 Create a table and perform the search operation on table 70-95 CO4
using indexing and non-indexing techniques
EXPERIMENT1
AIM: Creation, altering and droping of tables and inserting rows into a table (use constraints while
Creating Tables
create command is also used to create a table. We can specify names and datatypes of various columns
along. Following is the Syntax,
create table command will tell the database system to create a new table with given table name and
column information.
Example for Creating a database called COMPANY consisting of two tables – EMP &
DEPT
SQL> Create Table Dept (Deptno Number(2) Primary Key, Dname Varchar2(14), Loc Varchar2(13) );
SQL> Create Table Emp (Empno Int Primary Key, Ename Varchar(20) , Job Varchar2(10) ,Mgr Int, Hiredate
Date, Sal Int ,Comm Int, Deptno Int, foreign key(deptno) references Dept(Deptno));
ENAME VARCHAR2(10)
JOB VARCHAR2(9)
MGR NUMBER(4)
HIREDATE DATE
SAL NUMBER(7,2)
COMM NUMBER(7,2)
DEPTNO NUMBER(2)
Selecting a Table
Select command is used to retrieve data from a tables. It is the most used SQL query. We can retrieve
complete tables, or partial by mentioning conditions using WHERE clause.
Syntax
ALTERING TABLES
alter command is used for alteration of table structures. There are various uses of alter
command, such as,
Syntax,
To Drop a Column
alter command is also used to drop columns also. Following is the Syntax,
DROP COMMAND
drop command completely removes a table from database. This command will also destroy the
table structure.
Syntax,
Constraints are the rules enforced on data columns on table. These are used to limit the type of
data that can go into a table. This ensures the accuracy and reliability of the data in the database.
Constraints could be column level or table level. Column level constraints are applied only to one
column, whereas table level constraints are applied to the whole table.
UNIQUE Constraint
• The UNIQUE constraint uniquely identifies each record in a database table.
• The UNIQUE and PRIMARY KEY constraints both provide a guarantee for uniqueness for a column
or set of columns.
• A PRIMARY KEY constraint automatically has a UNIQUE constraint defined on it.
• Note that you can have many UNIQUE constraints per table, but only one PRIMARY KEY constraint
per table.
Example:
The following SQL creates a UNIQUE constraint on the "P_Id" column when the "Persons" table is
created:
• To allow naming of a UNIQUE constraint, and for defining a UNIQUE constraint on multiple
columns, use the following SQL syntax:
• To create a UNIQUE constraint on the "P_Id" column when the table is already created, use the
following SQL:
Example
• The PRIMARY KEY constraint uniquely identifies each record in a database table.
• Primary keys must contain UNIQUE values.
• A primary key column cannot contain NULL values.
• Most tables should have a primary key, and each table can have only ONE primary key.
The following SQL creates a PRIMARY KEY on the "P_Id" column when the "Persons" table is created:
To allow naming of a PRIMARY KEY constraint, and for defining a PRIMARY KEY constraint on multiple
columns, use the following SQL syntax:
To create a PRIMARY KEY constraint on the "P_Id" column when the table is already created, use the
following SQL:
CHECK Constraint
• The CHECK constraint is used to limit the value range that can be placed in a column.
• If you define a CHECK constraint on a single column it allows only certain values for this column.
• If you define a CHECK constraint on a table it can limit the values in certain columns based on
values in other columns in the row.
The following SQL creates a CHECK constraint on the "P_Id" column when the "Persons" table is created.
The CHECK constraint specifies that the column "P_Id" must only include integers greater than 0.
To create a CHECK constraint on the "P_Id" column when the table is already created, use the following
SQL:
DEFAULT Constraint
The default value will be added to all new records, if no other value is specified.
The following SQL creates a DEFAULT constraint on the "City" column when the "Persons" table is created:
SQL> CREATE TABLE Persons
(
P_Id int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255) DEFAULT 'Sandnes'
);
To create a DEFAULT constraint on the "City" column when the table is already created, use the following
SQL:
➢ A foreign key is a key used to link two tables together. This is sometimes called a
referencing key.
➢ Foreign Key is a column or a combination of columns whose values match a Primary Key
in a different table.
➢ The relationship between 2 tables matches the Primary Key in one of the tables with a
Foreign Key in the second table.
Example
Let's illustrate the foreign key with an example. Look at the following two tables:
1 77895 3
2 44678 3
3 22456 2
4 24562 1
➢ Note that the "P_Id" column in the "Orders" table points to the "P_Id" column in the "Persons"
table.
➢ The "P_Id" column in the "Persons" table is the PRIMARY KEY in the "Persons" table.
➢ The "P_Id" column in the "Orders" table is a FOREIGN KEY in the "Orders" table.
➢ The FOREIGN KEY constraint is used to prevent actions that would destroy links between tables.
➢ The FOREIGN KEY constraint also prevents invalid data from being inserted into the foreign key
column, because it has to be one of the values contained in the table it points to.
The following SQL creates a FOREIGN KEY on the "P_Id" column when the "Orders" table is created:
To create a FOREIGN KEY constraint on the "P_Id" column when the "Orders" table is already created, use
the following SQL:
SQL> ALTER TABLE Orders ADD FOREIGN KEY (P_Id) REFERENCES Persons(P_Id);
EXPERIMENT2
Queries (along with sub Queries) using ANY, ALL, IN, EXISTS, NOTEXISTS, UNION,
INTERSET, Constraints.
The ALL comparison condition is used to compare a value to a list or subquery. It must be preceded
by =, !=, >, <, <=, >= and followed by a list or subquery.
When the ALL condition is followed by a list, the optimizer expands the initial condition to all
elements of the list and strings them together with AND operators, as shown below.
Example Queries:
To find Employees data whose employee salary should above 2000 and 3000 and 4000
Sql> SELECT empno, sal FROM emp WHERE sal > ALL (2000, 3000, 4000);
Result:
EMPNO SAL
---------- ----------
7839 5000
- Transformed to equivalent statement without ALL.
SQL> SELECT empno, sal FROM emp WHERE sal > 2000 AND sal > 3000 AND sal > 4000;
Result:
EMPNO SAL
---------- ----------
7839 5000
When the ALL condition is followed by a subquery, the optimizer performs a two-step
transformation as shown below.
SQL> SELECT e1.empno, e1.sal FROM emp e1 WHERE e1.sal > ALL (SELECT e2.sal
FROM emp e2 WHERE e2.deptno = 20);
Result:
EMPNO SAL
---------- ----------
7839 5000
ANY
The ANY comparison condition is used to compare a value to a list or subquery. It must be preceded
by =, !=, >, <, <=, >= and followed by a list or subquery.
When the ANY condition is followed by a list, the optimizer expands the initial condition to all
elements of the list and strings them together with OR operators, as shown below.
Example Queries:
To find Employees data whose employee salary having more than 2000 or 3000 or 4000
SQL> SELECT empno, sal FROM emp WHERE sal > ANY (2000, 3000, 4000);
Result:
EMPNO SAL
---------- ----------
7566 2975
7698 2850
7782 2450
7788 3000
7839 5000
7902 3000
-- Transformed to equivalent statement without ANY.
SQL> SELECT empno, sal FROM emp WHERE sal > 2000 OR sal > 3000 OR sal > 4000;
Result:
EMPNO SAL
---------- ----------
7566 2975
7698 2850
7782 2450
7788 3000
7839 5000
7902 3000
When the ANY condition is followed by a subquery, the optimizer performs a single transformation
as shown below.
SQL> SELECT e1.empno, e1.sal FROM emp e1 WHERE e1.sal > ANY (SELECT e2.sal
FROM emp e2 WHERE e2.deptno = 10);
Result:
EMPNO SAL
---------- ----------
7839 5000
7902 3000
7788 3000
7566 2975
7698 2850
7782 2450
7499 1600
7844 1500
The IN Operator
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1,value2,...);
Example Queries:
Result:
------
The EXISTS condition is used in combination with a subquery and is considered to be met, if the
subquery returns at least one row. It can be used in a SELECT, INSERT, UPDATE, or DELETE
statement.
Syntax
Example Queries:
Using EXISTS constraint.
SQL> SELECT ENAME FROM EMP E WHERE EXISTS(SELECT DEPTNO FROM DEPT D WHERE
D.DNAME=’SALES’ AND D.DEPTNO=E.DEPTNO);
Result :
SQL> SELECT ENAME FROM EMP E WHERE NOT EXISTS(SELECT DEPTNO FROM DEPT D WHERE
D.DNAME=’SALES’ AND D.DEPTNO=E.DEPTNO);
Result :
Union
UNION is used to combine the results of two or more Select statements. However it will eliminate
duplicate rows from its result set. In case of union, number of columns and datatype must be same
in both the tables.
Example Query: To combine enames whose employee deptloc is DALLAS and whose employee
DNAME is ACCOUNTING.
SQL> SELECT ENAME FROM EMP E, DEPT D WHERE E.DEPTNO=D.DEPTNO AND D.LOC='DALLAS'
UNION
Result :
Intersect
Intersect operation is used to combine two SELECT statements, but it only retuns the records
which are common from both SELECT statements. In case of Intersect the number of columns
and datatype must be same. MySQL does not support INTERSECT operator.
Example Query: To find enames whose employee deptloc having DALLAS and DNAME
having RESEARCH.
SQL> SELECT ENAME FROM EMP E, DEPT D WHERE E.DEPTNO=D.DEPTNO AND D.LOC='DALLAS'
INTERSECT
EXPERIMENT 3
AGGREGATE FUNCTIONS
The SQL aggregate functions, as their title suggests are used to retrieve minimum and
maximum values from a column, to sum values in a column, to get the average of a
column values, or to simply count a number of records according to a search condition
(or lack of it). The SQL aggregate functions are
1. COUNT()
2. SUM()
3. MAX()
4. MIN()
5. AVG()
COUNT()
The COUNT() function returns the number of rows that matches a specified criteria.
The most commonly used SQL aggregate function is the COUNT function.
COUNT(column_name) Syntax
The COUNT(column_name) function returns the number of values (NULL values will not be counted) of
the specified column:
SELECT COUNT(column_name) FROM table_name;
COUNT(*) Syntax
The COUNT(DISTINCT column_name) function returns the number of distinct values of the specified
column:
The MIN() function returns the smallest value of the selected column.
Syntax
SELECT MIN(column_name) FROM table_name;
The MAX() function returns the largest value of the selected column.
Syntax
SELECT MAX(column_name) FROM table_name;
Syntax
SELECT AVG(column_name) FROM table_name;
The SUM() Function
The SUM() function returns the total sum of a numeric column.
Syntax
SELECT SUM(column_name) FROM table_name;
Result :
Result :
COUNT(DISTINCTJOB)
Result:
SUM(SAL)
---------
29025
GROUP BY AND ORDER BY AND HAVING CLAUSE
The SQL GROUP BY clause can be used in a SELECT statement to collect data across multiple
records and group the results by one or more columns.
The GROUP BY statement is used in conjunction with the aggregate functions to group the result-set by
one or more columns.
GROUP BY Syntax:
SELECT column1, column2
FROM table_name
WHERE [ conditions ]
GROUP BY column1
The HAVING clause enables you to specify conditions that filter which group results appear in
the final results.
The WHERE clause places conditions on the selected columns, whereas the HAVING clause
places conditions on groups created by the GROUP BY clause.
The HAVING clause must follow the GROUP BY clause in a query and must also precede the
ORDER BY clause if used. The following is the syntax of the SELECT statement, including the
HAVING clause:
ORDER BY syntax
Examples:
RESULT:
JOB SUM(SAL)
--------- ----------
CLERK 4150
SALESMAN 5600
PRESIDENT 5000
MANAGER 8275
ANALYST 6000
SELECT DEPTNO, MAX (SAL) FROM EMP GROUP BY DEPTNO HAVING MAX
(SAL)>(SELECT MAX(SAL) FROM EMP WHERE DEPTNO=30);
RESULT:
CREATING AND DROPING VIEWS
Views can be considered as virtual tables. Generally speaking, a table has a set of definition, and
it physically stores the data. A view also has a set of definitions, which is build on top of table(s)
or other view(s), and it does not physically store the data.
Syntax
DROPPING A VIEW:
Queries using Conversion functions (to_char, to_number and to_date), string functions (Concatenation,
lpad, rpad, ltrim, rtrim, lower, upper, initcap, length, substr and instr), date
functions (Sysdate, next_day, add_months, last_day, months_between, least, greatest, trunc, round,
to_char, to_date)
SYSDATE
Returns the current system date of the database system.
Syntax:
SYSDATE
28-May-2016
ADD_MONTHS(Date, months_to_add)
Returns the month by adding n months to the month of the date specified.
Syntax:
add_months( date1, n )
Output:
01-Nov-03
LAST_DAY(Date)
Returns the last day of the date specified.
Syntax:
LAST_DAY(date1)
Output:
MONTHS_BETWEEN(Date1, Date2)
Returns the number of months between date1 and date2
Syntax:
MONTHS_BETWEEN(date1,date2)
Output:
ADDDATE(expr,days)
When invoked with the INTERVAL form of the second argument, ADDDATE() is a synonym for
DATE_ADD().
SQL> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY) from dual;;
Output:
+---------------------------------------------------------+
| DATE_ADD('1998-01-02', INTERVAL 31 DAY) |
+---------------------------------------------------------+
| 1998-02-02
CURDATE()
Returns the current date as a value in 'YYYY-MM-DD' or YYYYMMDD format, depending on
whether the function is used in a string or numeric context.
SQL> SELECT CURDATE() from dual;;
Output:
+---------------------------------------------------------+
| CURDATE() |
+---------------------------------------------------------+
| 1997-12-15 |
+-------------
CURTIME()
Returns the current time as a value in 'HH:MM:SS' or HHMMSS format, depending on whether
the function is used in a string or numeric context. The value is expressed in the current time zone.
Output:
| CURTIME() |
+---------------------------------------------------------+
| 23:50:26 |
+---------------
DATE(expr)
+---------------------------------------------------------+
| DATE('2003-12-31 01:02:03') |
+---------------------------------------------------------+
| 2003-12-31
DAYNAME(date)
+---------------------------------------------------------+
| DAYNAME('1998-02-05') |
+---------------------------------------------------------+
| Thursday
DAYOFMONTH(date)
Returns the day of the month for date, in the range 0 to 31.
| DAYOFMONTH('1998-02-03') |
|3 |
DAYOFWEEK(date)
Returns the weekday index for date (1 = Sunday, 2 = Monday, ., 7 = Saturday). These index values
correspond to the ODBC standard.
+---------------------------------------------------------+
|DAYOFWEEK('1998-02-03') |
+---------------------------------------------------------+
|3 |
DAYOFYEAR(date)
Returns the day of the year for date, in the range 1 to 366.
+---------------------------------------------------------+
| DAYOFYEAR('1998-02-03') |
+---------------------------------------------------------+
| 34
MINUTE(time)
+---------------------------------------------------------+
| MINUTE('98-02-03 10:05:03') |
+---------------------------------------------------------+
|5 |
MONTH(date)
+---------------------------------------------------------+
| MONTH('1998-02-03') |
+---------------------------------------------------------+
|2 |
MONTHNAME(date)
+---------------------------------------------------------+
| MONTHNAME('1998-02-05') |
+---------------------------------------------------------+
| February |
SECOND(time)
Output:
SUBDATE(expr,days)
When invoked with the INTERVAL form of the second argument, SUBDATE() is a synonym for
DATE_SUB(). For information on the INTERVAL unit argument, see the discussion for
DATE_ADD().
+---------------------------------------------------------+
| DATE_SUB('1998-01-02', INTERVAL 31 DAY) |
+---------------------------------------------------------+
| 1997-12-02
TIME(expr)
Extracts the time part of the time or datetime expression expr and returns it as a string.
+---------------------------------------------------------+
| TIME('2003-12-31 01:02:03') |
+---------------------------------------------------------+
| 01:02:03
YEAR(date)
Returns the year for date, in the range 1000 to 9999, or 0 for the .zero. date.
+---------------------------------------------------------+
| YEAR('98-02-03') |
+---------------------------------------------------------+
| 1998
TIMESTAMPADD(unit,interval,datetime_expr)
Adds the integer expression interval to the date or datetime expression datetime_expr.
+---------------------------------------------------------+
| TIMESTAMPADD(MINUTE,1,'2003-01-02') |
+---------------------------------------------------------+
| 2003-01-02 00:01:00
TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2)
Returns the integer difference between the date or datetime expressions datetime_expr1 and
datetime_expr2.
+---------------------------------------------------------+
| TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01') |
+---------------------------------------------------------+
|3
NUMERIC FUNCTIONS
ABS(number)
Returns the absolute positive value of an expression.
Syntax:
ABS(expression)
Example:
Output:
1.0 .0
CEIL(number)
Returns the smallest integer greater than, or equal to, the specified numeric expression.
Syntax:
CEIL (expression)
Example:
Output:
224.00 -223.00
FLOOR(number)
Returns the largest integer less than, or equal to, the specified numeric expression.
Syntax:
FLOOR(expression)
Example:
Output:
223.00 -224.00
MOD(number, divisor)
Returns the remainder of the division from 2 integer values.
Syntax:
MOD(dividend, divisor)
Example:
Output:
POWER(number, power)
Returns the exponential value for the numeric expression.
Syntax:
POWER(number, power)
Example:
Output:
8.0
SIGN(number)
Returns the sign i.e. positive or negative value for the numeric expression. It returns -1 for negative
expressions, a value of 0 for zero
Syntax:
SIGN(number)
Example:
Output:
1
ROUND(number, precision)
Returns the numeric value rounded off to the next value specified.
Syntax:
Example:
SQRT(number)
Returns the square root value of the expression.
Syntax:
SQRT(number)
Example:
Output:
2.0
TRUNC(number, precision)
Returns a numeric value that truncate to the specific places
Syntax:
TRUNC (number,places)
Example:
Output:
1.34
ACOS(X)
This function returns the arccosine of X. The value of X must range between -1 and 1 or NULL will be
returned. Consider the following example:
Output:
+---------------------------------------------------------+
| ACOS(1) |
| 0.000000
ASIN(X)
The ASIN() function returns the arcsine of X. The value of X must be in the range of -1 to 1 or
NULL is returned.
+---------------------------------------------------------+
| ASIN(1) |
+---------------------------------------------------------+
| 1.5707963267949
ATAN(X)
+---------------------------------------------------------+
| ATAN(1) |
+---------------------------------------------------------+
| 0.78539816339745
COS(X)
+---------------------------------------------------------+
| COS(90) |
+---------------------------------------------------------+
| -0.44807361612917
COT(X)
+---------------------------------------------------------+
| COT(1) |
+---------------------------------------------------------+
| 0.64209261593433
SIN(X)
This function returns the sine of X. Consider the following example:
SQL>SELECT SIN(90) from dual;
Output:
+---------------------------------------------------------+
| SIN(90) |
+---------------------------------------------------------+
| 0.893997
TAN(X)
This function returns the tangent of the argument X, which is expressed in radians.
+---------------------------------------------------------+
| TAN(45) |
+---------------------------------------------------------+
| 1.619775 |
+-----------
EXP(X)
This function returns the value of e (the base of the natural logarithm) raised to the power of X.
+---------------------------------------------------------+
| EXP(3) |
+---------------------------------------------------------+
| 20.085537
GREATEST(n1,n2,n3,..........)
The GREATEST() function returns the greatest value in the set of input parameters (n1, n2, n3, a
nd so on). The following example uses the GREATEST() function to return the largest number
from a set of numeric values:
+---------------------------------------------------------+
| GREATEST(3,5,1,8,33,99,34,55,67,43) |
+---------------------------------------------------------+
| 99 |
+------------------------------------------------
LEAST(N1,N2,N3,N4,......)
The LEAST() function is the opposite of the GREATEST() function. Its purpose is to return the
least-valued item from the value list (N1, N2, N3, and so on). The following example shows the
proper usage and output for the LEAST() function:
+---------------------------------------------------------+
| LEAST(3,5,1,8,33,99,34,55,67,43) |
|1
|
LOG
LOG returns the logarithm, base n2, of n1. The base n1 can be any positive value other than 0 or 1
and n2 can be any positive value.
Example
STRING FUNCTIONS
ASCII
The SQL function ASCII converts a character in the numeric ascii value. If the string is larger as one
character then the ascii value of the first characters is return.
Syntax:
ASCII( string )
Examples:
Output:
Return Values: 65
CHR()
Syntax:
CHR( expression )
Examples:
CONCAT(string1, string2)
Combines result from several different fields.
Syntax:
CONCAT(string1, string2)
Example:
INITCAP(string)
Returns a string with each word's first character in uppercase and the rest in lowercase.
Syntax:
INITCAP(character-expression)
Example:
Output:
Analyst
LENGTH(string)
Returns the length of the string. Also called as LEN()in sql server.
Syntax:
LENGTH(string)
Example:
Output:
LPAD(string, #,padding_char)
Used to pad the string to left to length n characters. string_pad parameter is optional. If not specified,
string will be padded spaces to the left-side of string.
Syntax:
Example:
Output:
‘ tech’
RPAD(string, #,padding_char)
Used to pad the string to right to length n characters.string_pad parameter is optional. If not specified,
string will be padded spaces to the right-side of string.
Syntax:
rpad ('string', n [, 'string_pad')
Example:
Output:
‘tech ’
LTRIM(string,searchString)
Used to remove all white spaces from the beginning of the string.
Syntax:
Ltrim(string)
Example:
Output:
‘Sample ’
RTRIM(string,searchString)
Used to remove all white spaces at the end of the string.
Syntax:
rtrim(string)
Example:
Output:
‘ Sample’
REPLACE(string,searchString,replacement)
Used to replace the string1, having string2 with string3.
Syntax:
Example:
SUBSTR(str,pos,len):
Example:
Output:
‘an D’
UPPER(string)
Returns a string in lowercase converted to uppercase
Syntax:
UPPER(string):
Example:
Output: SAND
LOWER(string)
Returns a string in uppercase converted to lowercase
Syntax:
LOWER(string):
Example:
Output:
sand
BIN(N)
Returns a string representation of the binary value of N, where N is a longlong (BIGINT) number.
SQL> SELECT BIN(12) from dual;
Output:
+---------------------------------------------------------+
| BIN(12) |
+---------------------------------------------------------+
| 1100
INSERT(str,pos,len,newstr)
Returns the string str, with the substring beginning at position pos and len characters long replaced
by the string newstr.
SQL> SELECT INSERT('Quadratic', 3, 4, 'What')v from dual;
Output:
| INSERT('Quadratic', 3, 4, 'What') |
+---------------------------------------------------------+
| QuWhattic
INSTR(str,substr)
Returns the position of the first occurrence of substring substr in string str.
+---------------------------------------------------------+
| INSTR('foobarbar', 'bar') |
|4
LEFT(str,len)
Returns the leftmost len characters from the string str, or NULL if any argument is NULL.
+---------------------------------------------------------+
| LEFT('foobarbar', 5) |
+---------------------------------------------------------+
| fooba
REPEAT(str,count)
Returns a string consisting of the string str repeated count times. If count is less than 1, returns an
empty string. Returns NULL if str or count are NULL.
+---------------------------------------------------------+
| REPEAT('SQL', 3) |
+---------------------------------------------------------+
| SQLSQLSQL
REVERSE(str)
Returns the string str with the order of the characters reversed.
+---------------------------------------------------------+
| REVERSE('abcd') |
+---------------------------------------------------------+
| dcba
RIGHT(str,len)
Returns the rightmost len characters from the string str, or NULL if any argument is NULL.
+---------------------------------------------------------+
| RIGHT('foobarbar', 4) |
+---------------------------------------------------------+
| rbar
STRCMP(str1, str2)
Compares two strings and returns 0 if both strings are equal, it returns -1 if the first argument is
smaller than the second according to the current sort order otherwise it returns 1.
+---------------------------------------------------------+
| STRCMP('MOHD', 'MOHD') |
+---------------------------------------------------------+
|0
COVERSION FUNCTIONS
1. TO_CHAR
Syntax
or
Example:
Result: '2003/07/09'
2. TO_NUMBER function
The TO_NUMBER function converts a character string of type CHAR or VARCHAR2 into a number.
The following example converts the string 97.13 to a number using TO_NUMBER():
Output:
TO_NUMBER('97.13')
------------------
97.13
3. TO_DATE
Syntax
to_date(char[,'format'[,nls_lang])
to_date will convert either a character string or an expression into a date value.
The 'format' must be a valid DATE format: YYYY=year, MM=month, DD=Day, HH=Hour,
Mi=Minute
If no format is specified Oracle will assume the default date format has been supplied in char.
Example 1
Result:
2010 01 05 00:00:00
Example 2
Result:
1999 01 05 00:00:00
EXPERIMENT 5
5. i)Creation of simple PL/SQL program which includes declaration section, executable section and
exception –Handling section (Ex. Student marks can be selected from the table and printed for those
who secured first class and an exception can be raised if no records were found)
ii) Insert data into student table and use COMMIT, ROLLBACK and SAVEPOINT in PL/SQL block.
Introduction to PL/SQL
The PL/SQL programming language was developed by Oracle Corporation in the late 1980s as
procedural extension language for SQL and the Oracle relational database.
PL/SQL is a very secure functionality tool for manipulating, controlling, validating, and
restricting unauthorized access data from the SQL database.
PL/SQL have a great functionality to display multiple records from the multiple tables at the
same time.
PL/SQL is capable to send entire block of statements and execute it in the Oracle engine at
once.
Advantages PL/SQL
Procedural language support : PL/SQL is a development tools not only for data manipulation
futures but also provide the conditional checking, looping or branching operations same as
like other programming language.
Reduces network traffic : This one is great advantages of PL/SQL. Because PL/SQL nature
is entire block of SQL statements execute into oracle engine all at once so it's main benefit
is reducing the network traffic.
Error handling : PL/SQL is dealing with error handling, It's permits the smart way handling
the errors and giving user friendly error messages, when the errors are encountered.
Declare variable : PL/SQL gives you control to declare variables and access them within the
block. The declared variables can be used at the time of query processing.
Intermediate Calculation : Calculations in PL/SQL done quickly and efficiently without using
Oracle engines. Thisimproves the transaction performance.
Portable application : Applications are written in PL/SQL are portable in any Operating
system. PL/SQL applications are independence program to run any computer.
AIM: Creation of simple PL/SQL program which includes declaration section, executable section and
exception –Handling section (Ex. Student marks can be selected from the table and printed for those
who secured first class and an exception can be raised if no records were found)
Oracle PL/SQL transaction oriented language. Oracle transactions provide a data integrity.
PL/SQL transaction is a series of SQL data manipulation statements that are work logical unit.
Transaction is an atomic unit all changes either committed or rollback.
At the end of the transaction that makes database changes, Oracle makes all the changes
permanent save or may be undone. If your program fails in the middle of a transaction, Oracle
detect the error and rollback the transaction and restoring the database.
You can use the COMMIT, ROLLBACK, SAVEPOINT, and SET TRANSACTION command
to control the transaction.
1. COMMIT : COMMIT command to make changes permanent save to a database during the current
transaction.
2. ROLLBACK : ROLLBACK command execute at the end of current transaction and undo/undone any
changes made since the begin transaction.
3. SAVEPOINT : SAVEPOINT command save the current point with the unique name in the processing of
a transaction.
4. AUTOCOMMIT : Set AUTOCOMMIT ON to execute COMMIT Statement automatically.
5. SET TRANSACTION : PL/SQL SET TRANSACTION command set the transaction properties such as read-
write/read only access.
AIM: Insert data into student table and use COMMIT, ROLLBACK and SAVEPOINT in PL/SQL block.
Begin
insert into student(sid,sname,branch,sage,marks) values (512,'gourav','cse',22,89.4);
Savepoint A;
insert into student(sid,sname,branch,sage,marks) values (524,'gireesh','ece',21,90.5);
Savepoint B;
insert into student(sid,sname,branch,sage,marks) values (540,'goutam','eee',20,92.6);
Savepoint C;
Rollback to B;
Commit;
End;
ROLLBACK TO SAVEPOINT A;
EXPERIMENT 6
Develop a program that includes the features NESTED IF, CASE and CASE expression. The
program can be extended using the NULLIF and COALESCE functions.
PL/SQL IF THEN ELSE conditional control statements. PL/SQL Conditional Control two
type: IF THEN ELSE statement and CASE statement,
PL/SQL IF statement check condition and transfer the execution flow on that matched block
depending on a condition. IF statement execute or skip a sequence of one or more statements.
PL/SQL IF statement four different type,
1. IF THEN Statement
2. IF THEN ELSE Statement
3. IF THEN ELSIF Statement
4. Nested IF THEN ELSE Statement
IF THEN Statement
IF ( condition ) THEN
statement
END IF;
IF THEN ELSE Statement
IF ( condition ) THEN
statement;
ELSE
statement;
END IF;
IF ( condition-1 ) THEN
statement-1;
statement-2;
statement-3;
ELSE
statement;
END IF;
Logically IF THEN ELSIF Statement and Nested IF THEN ELSE Statement both are same.
Nested IF THEN ELSE Statement write in following syntax format:
IF ( condition-1 ) THEN
statement-1;
ELSE
IF ( condition-2 ) THEN
statement-2;
ELSE
IF ( condition-3 ) THEN
statements-3;
END IF;
END IF;
END IF;
CASE Statement
PL/SQL simple CASE statement evaluates selector and attempt to match one or more WHEN
condition.
Syntax
CASE selector
WHEN value-1
THEN statement-1;
WHEN value-2
THEN statement-2;
ELSE
statement-3;
END CASE
AIM:
Develop a program that includes the features NESTED IF, CASE and CASE expression. The
program can be extended using the NULLIF and COALESCE functions.
Declare
vno number:=&anynumber;
vresult varchar2(20);
Begin
If vno<10 then
vno:=vno+1;
else
if vno>10 then
vno:=vno-1;
else
vno:=vno+10;
end if;
end if;
case
end case;
vresult:=case when mod(vno,2)=0
then
else
end;
dbms_output.put_line(vresult);
end;
Result:
EXPERIMENT 7
Program development using WHILE LOOPS, numeric FOR LOOPS, nested loops using ERROR
Handling, BUILT –IN Exceptions, USER defined Exceptions, RAISE- APPLICATION ERROR.
WHILE<condition>
LOOP
<action>
ENDLOOP;
Program:
DECLARE
no NUMBER := 0;
BEGIN
END LOOP;
END;
Result
Sum : 10
<Action>
ENDLOOP;
Program:
BEGIN
FOR no IN 1 .. 5 LOOP
END LOOP;
END;
/
Result
Iteration : 1
Iteration : 2
Iteration : 3
Iteration : 4
Iteration : 5
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
exception1-handling-statements
exception2-handling-statements
exception3-handling-statements
........
END;
Example:
Let us write some simple code to illustrate the concept. We will be using the CUSTOMERS table
we had created and used in the previous chapters:
DECLARE
c_id customers.id%type := 8;
c_name customers.name%type;
c_addr customers.address%type;
BEGIN
FROM customers
WHERE id = c_id;
EXCEPTION
dbms_output.put_line('Error!');
END;
/
When the above code is executed at SQL prompt, it produces the following result:
No such customer!
The above program displays the name and address of a customer whose ID is given. Since there
is no customer with ID value 8 in our database, the program raises the run-time
exception NO_DATA_FOUND, which is captured inEXCEPTION block.
Raising Exceptions
Exceptions are raised by the database server automatically whenever there is any internal database
error, but exceptions can be raised explicitly by the programmer by using the command RAISE.
Following is the simple syntax of raising an exception:
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
statement;
END;
You can use above syntax in raising Oracle standard exception or any user-defined exception.
Next section will give you an example on raising user-defined exception, similar way you can
raise Oracle standard exceptions as well.
User-defined Exceptions
PL/SQL allows you to define your own exceptions according to the need of your program. A
user-defined exception must be declared and then raised explicitly, using either a RAISE
statement or the procedure DBMS_STANDARD.RAISE_APPLICATION_ERROR.
DECLARE
my-exception EXCEPTION;
Example:
The following example illustrates the concept. This program asks for a customer ID, when the
user enters an invalid ID, the exception invalid_id is raised.
DECLARE
c_name customers.name%type;
c_addr customers.address%type;
ex_invalid_id EXCEPTION;
BEGIN
RAISE ex_invalid_id;
ELSE
FROM customers
WHERE id = c_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| c_name);
END IF;
EXCEPTION
dbms_output.put_line('Error!');
END;
When the above code is executed at SQL prompt, it produces the following result:
PL/SQL Procedures
PL/SQL procedures create using CREATE PROCEDURE statement. The major difference
between PL/SQL function or procedure, function return always value where as procedure may
or may not return value.
When you create a function or procedure, you have to define IN/OUT/INOUT parameters
parameters.
1. IN : IN parameter referring to the procedure or function and allow to overwritten the value of
parameter.
2. OUT : OUT parameter referring to the procedure or function and allow to overwritten the value of
parameter.
3. IN OUT : Both IN OUT parameter referring to the procedure or function to pass both IN OUT parameter,
modify/update by the function or procedure and also get returned.
IN/OUT/INOUT parameters you define in procedure argument list that get returned back to a
result. When you create the procedure default IN parameter is passed in argument list. It's means
value is passed but not returned. Explicitly you have define OUT/IN OUT parameter in
argument list.
[local declarations ];
BEGIN
END;
Program:
ii) Program development using creation of procedures passing parameters IN and OUT of
Procedure:
create or replace procedure query_emp(p_id in emp.empno%type,p_name out emp.ename%type,p_sal
out emp.sal%type,p_deptno out emp.deptno%type) is
Begin
select ename,sal,deptno into p_name, p_salary , p_deptno from emp where empno=p_id;
End query_emp;
______________
Variable gn varchar2(15)
Variable gs number
Variable gc number
SQL> print gn gs gc
GN
--------
WARD
GS
----------
422.96
GC
----------
500
EXPERIMENT 9
Program development using creation of stored functions, invoke functions in SQL Statements and write
complex functions.
Aim:
Program development using creation of stored functions, invoke functions in SQL Statements
and write complex functions.
{ IS | AS}
[Local declarations/Calculation/etc.,]
BEGIN
Exception handlers]
END [name];
BEGIN
END;
Program:
return number
is
emptot number;
Begin
return emptot;
End;
( p_id in emp.empno%type)
return number
is
vsal emp.sal%type ;
Begin
select sal
into vsal
from emp
return vsal;
end get_sal;
To execute:
Function:
( p_id in emp.empno%type)
return number
is
vsal emp.sal%type ;
Begin
return vsal;
end get_sal;
To execute:
Develop programs using features parameters in a CURSOR, FOR UPDATE CURSOR, WHERE CURRENT of
clause and CURSOR variables.
IS query
OPEN <cursor-name>;
<SELECT statement…>
Program:
1. Create a Cursor to find employee with given job and deptno. Develop programs using features
parameters in a CURSOR, FOR UPDATE CURSOR, WHERE CURRENT of clause and CURSOR variables.
DECLARE
cursor sal_cursor is
select e.ename ,e.salary,e.deptno from employee e where e.deptno in (10,20,30) for update of
salary nowait;
Begin
savepoint a;
loop
if emp_record.deptno=10 then
update employee
end if;
if emp_record.deptno=20 then
update employee
set salary=emp_record.salary+emp_record.salary*0.2
end if;
if emp_record.deptno=30 then
update employee
end if;
end loop;
End;
EXPERIMENT 11
Develop Programs using BEFORE and AFTER Triggers, Row and Statement Triggers and
INSTEAD OF Triggers
Aim:
Develop Programs using BEFORE and AFTER Triggers, Row and Statement Triggers and INSTEAD OF
Triggers.
ON table_name
Variable declaration;
Constant declaration;
BEGIN
Program:
Trigger:
SQL> create or replace trigger tg2 after insert on emp for each row when ( new.sal > 10000)
Begin
dbms_output.put_line(' salary out of range ');
End;
SQL> create or replace trigger tg2 after insert on emp for each row when ( new.sal > 10000)
Begin
End;
SQL> create or replace trigger k1 after insert on emp for each row when ( new.hiredate > sysdate)
Begin
dbms_output.put_line( ' Wrong date ');
End;
Begin
End;
EXPERIMENT 12
Create a table and perform the search operation on table using indexing and non-indexing
techniques
Aim:
Create a table and perform the search operation on table using indexing and non-indexing
techniques
A key is a set of columns or expressions on which you can build an index. Although the terms
are often used interchangeably, indexes and keys are different. Indexes are structures stored in
the database that users manage using SQL statements. Keys are strictly a logical concept.
The following statement creates an index on the customer_id column of the sample
table oe.orders:
CREATE INDEX ord_customer_ix ON orders (customer_id);
In the preceding statement, the customer_id column is the index key. The index itself is
named ord_customer_ix.
Composite Indexes
Composite indexes can speed retrieval of data for SELECT statements in which the WHERE clause
references all or the leading portion of the columns in the composite index. Therefore, the order
of the columns used in the definition is important. In general, the most commonly accessed
columns go first.
Queries that access all three columns, only the last_name column, or only
the last_name and job_id columns use this index. In this example, queries that do not access
the last_name column do not use the index.
Indexes can be unique or nonunique. Unique indexes guarantee that no two rows of a table have
duplicate values in the key column or columns. For example, no two employees can have the
same employee ID. Thus, in a unique index, one rowid exists for each data value. The data in the
leaf blocks is sorted only by key.
Nonunique indexes permit duplicates values in the indexed column or columns. For example,
the first_name column of the employees table may contain multiple Mike values. For a
nonunique index, the rowid is included in the key in sorted order, so nonunique indexes are
sorted by the index key and rowid (ascending).
Oracle Database does not index table rows in which all key columns are null, except for bitmap
indexes or when the cluster key column value is null.
Types of Indexes
Oracle Database provides several indexing schemes, which provide complementary performance
functionality. The indexes can be categorized as follows:
• B-tree indexes
These indexes are the standard index type. They are excellent for primary key and highly-
selective indexes. Used as concatenated indexes, B-tree indexes can retrieve data sorted
by the indexed columns. B-tree indexes have the following subtypes:
o Index-organized tables
An index-organized table differs from a heap-organized because the data is itself the
index. See "Overview of Index-Organized Tables".
In this type of index, the bytes of the index key are reversed, for example, 103 is
stored as 301. The reversal of bytes spreads out inserts into the index over many
blocks. See "Reverse Key Indexes".
o Descending indexes
This type of index is used to index a table cluster key. Instead of pointing to a row,
the key points to the block that contains rows related to the cluster key.
See "Overview of Indexed Clusters".
In a bitmap index, an index entry uses a bitmap to point to multiple rows. In contrast, a
B-tree index entry points to a single row. A bitmap join index is a bitmap index for the
join of two or more tables. See "Bitmap Indexes".
• Function-based indexes
• This type of index includes columns that are either transformed by a function, such as
the UPPER function, or included in an expression. B-tree or bitmap indexes can be
function-based. See "Function-Based Indexes".
• Application domain indexes
This type of index is created by a user for data in an application-specific domain. The
physical index need not use a traditional index structure and can be stored either in the
Oracle database as tables or externally as a file. See "Application Domain Indexes".
B-Tree Indexes
B-trees, short for balanced trees, are the most common type of database index. A B-tree index is
an ordered list of values divided into ranges. By associating a key with a row or range of rows,
B-trees provide excellent retrieval performance for a wide range of queries, including exact
match and range searches.
Figure 3-1 illustrates the structure of a B-tree index. The example shows an index on
the department_id column, which is a foreign key column in the employees table.
A B-tree index has two types of blocks: branch blocks for searching and leaf blocks that store
values. The upper-level branch blocks of a B-tree index contain index data that points to lower-
level index blocks. In Figure 3-1, the root branch block has an entry 0-40, which points to the
leftmost block in the next branch level. This branch block contains entries such as 0-10 and 11-
19. Each of these entries points to a leaf block that contains key values that fall in the range.
A B-tree index is balanced because all leaf blocks automatically stay at the same depth. Thus,
retrieval of any record from anywhere in the index takes approximately the same amount of
time. The height of the index is the number of blocks required to go from the root block to a leaf
block. The branch level is the height minus 1. In Figure 3-1, the index has a height of 3 and a
branch level of 2.
Branch blocks store the minimum key prefix needed to make a branching decision between two
keys. This technique enables the database to fit as much data as possible on each branch block.
The branch blocks contain a pointer to the child block containing the key. The number of keys
and pointers is limited by the block size.
The leaf blocks contain every indexed data value and a corresponding rowid used to locate the
actual row. Each entry is sorted by (key, rowid). Within a leaf block, a key and rowid is linked to
its left and right sibling entries. The leaf blocks themselves are also doubly linked. In Figure 3-
1 the leftmost leaf block (0-10) is linked to the second leaf block (11-19).
Index Scans
In an index scan, the database retrieves a row by traversing the index, using the indexed column
values specified by the statement. If the database scans the index for a value, then it will find this
value in n I/Os where n is the height of the B-tree index. This is the basic principle behind Oracle
Database indexes.
If a SQL statement accesses only indexed columns, then the database reads values directly from
the index rather than from the table. If the statement accesses columns in addition to the indexed
columns, then the database uses rowids to find the rows in the table. Typically, the database
retrieves table data by alternately reading an index block and then a table block.
In a full index scan, the database reads the entire index in order. A full index scan is available if
a predicate (WHERE clause) in the SQL statement references a column in the index, and in some
circumstances when no predicate is specified. A full scan can eliminate sorting because the data
is ordered by index key.
FROM employees
Also assume that department_id, last_name, and salary are a composite key in an index.
Oracle Database performs a full scan of the index, reading it in sorted order (ordered by
department ID and last name) and filtering on the salary attribute. In this way, the database scans
a set of data smaller than the employees table, which contains more columns than are included
in the query, and avoids sorting the data.
For example, the full scan could read the index entries as follows:
50,Atkinson,2800,rowid
60,Austin,4800,rowid
70,Baer,10000,rowid
80,Abel,11000,rowid
80,Ande,6400,rowid
110,Austin,7200,rowid
A fast full index scan is a full index scan in which the database accesses the data in the index
itself without accessing the table, and the database reads the index blocks in no particular order.
Fast full index scans are an alternative to a full table scan when both of the following conditions
are met:
• The index must contain all columns needed for the query.
• A row containing all nulls must not appear in the query result set. For this result to be
guaranteed, at least one column in the index must have either:
o A NOT NULL constraint
o A predicate applied to it that prevents nulls from being considered in the query
result set
For example, an application issues the following query, which does not include an ORDER
BY clause:
FROM employees;
The last_name column has a not null constraint. If the last name and salary are a composite key
in an index, then a fast full index scan can read the index entries to obtain the requested
information:
Baida,2900,rowid
Zlotkey,10500,rowid
Austin,7200,rowid
Baer,10000,rowid
Atkinson,2800,rowid
Austin,4800,rowid
An index range scan is an ordered scan of an index that has the following characteristics:
The database commonly uses an index range scan to access selective data. The selectivity is the
percentage of rows in the table that the query selects, with 0 meaning no rows and 1 meaning all
rows. Selectivity is tied to a query predicate, such as WHERE last_name LIKE 'A%', or a
combination of predicates. A predicate becomes more selective as the value approaches 0 and
less selective (or more unselective) as the value approaches 1.
For example, a user queries employees whose last names begin with A. Assume that
the last_name column is indexed, with entries as follows:
Abel,rowid
Ande,rowid
Atkinson,rowid
Austin,rowid
Austin,rowid
Baer,rowid
The database could use a range scan because the last_name column is specified in the predicate
and multiples rowids are possible for each index key. For example, two employees are named
Austin, so two rowids are associated with the key Austin.
An index range scan can be bounded on both sides, as in a query for departments with IDs
between 10 and 40, or bounded on only one side, as in a query for IDs over 40. To scan the
index, the database moves backward or forward through the leaf blocks. For example, a scan for
IDs between 10 and 40 locates the first index leaf block that contains the lowest key value that is
10 or greater. The scan then proceeds horizontally through the linked list of leaf nodes until it
locates a value greater than 40.
In contrast to an index range scan, an index unique scan must have either 0 or 1 rowid
associated with an index key. The database performs a unique scan when a predicate references
all of the columns in a UNIQUE index key using an equality operator. An index unique scan stops
processing as soon as it finds the first record because no second record is possible.
SELECT *
FROM employees
WHERE employee_id = 5;
Assume that the employee_id column is the primary key and is indexed with entries as follows:
1,rowid
2,rowid
4,rowid
5,rowid
6,rowid
In this case, the database can use an index unique scan to locate the rowid for the employee
whose ID is 5.
An index skip scan uses logical subindexes of a composite index. The database "skips" through
a single index as if it were searching separate indexes. Skip scanning is beneficial if there are few
distinct values in the leading column of a composite index and many distinct values in the
nonleading key of the index.
The database may choose an index skip scan when the leading column of the composite index is
not specified in a query predicate. For example, assume that you run the following query for a
customer in the sh.customers table:
The customers table has a column cust_gender whose values are either M or F. Assume that a
composite index exists on the columns (cust_gender, cust_email). Example 3-1 shows a
portion of the index entries.
F,[email protected],rowid
F,[email protected],rowid
F,[email protected],rowid
F,[email protected],rowid
F,[email protected],rowid
F,[email protected],rowid
M,[email protected],rowid
M,[email protected],rowid
The database can use a skip scan of this index even though cust_gender is not specified in
the WHERE clause.
In a skip scan, the number of logical subindexes is determined by the number of distinct values
in the leading column. In Example 3-1, the leading column has two possible values. The database
logically splits the index into one subindex with the key F and a second subindex with the key M.
When searching for the record for the customer whose email is [email protected], the
database searches the subindex with the value F first and then searches the subindex with the
value M. Conceptually, the database processes the query as follows:
UNION ALL
The index clustering factor measures row order in relation to an indexed value such as
employee last name. The more order that exists in row storage for this value, the lower the
clustering factor.
The clustering factor is useful as a rough measure of the number of I/Os required to read an
entire table by means of an index:
• If the clustering factor is high, then Oracle Database performs a relatively high number of
I/Os during a large index range scan. The index entries point to random table blocks, so
the database may have to read and reread the same blocks over and over again to retrieve
the data pointed to by the index.
• If the clustering factor is low, then Oracle Database performs a relatively low number of
I/Os during a large index range scan. The index keys in a range tend to point to the same
data block, so the database does not have to read and reread the same blocks over and
over.
The clustering factor is relevant for index scans because it can show:
• Whether the database will use an index for large range scans
• The degree of table organization in relation to the index key
• Whether you should consider using an index-organized table, partitioning, or table cluster
if rows must be ordered by the index key
For example, assume that the employees table fits into two data blocks. depicts the rows in the
two data blocks (the ellipses indicate data that is not shown).
Data Block 1
Rows are stored in the blocks in order of last name (shown in bold). For example, the bottom
row in data block 1 describes Abel, the next row up describes Ande, and so on alphabetically
until the top row in block 1 for Steven King. The bottom row in block 2 describes Kochar, the
next row up describes Kumar, and so on alphabetically until the last row in the block for Zlotkey.
Assume that an index exists on the last name column. Each name entry corresponds to a rowid.
Conceptually, the index entries would look as follows:
Abel,block1row1
Ande,block1row2
Atkinson,block1row3
Austin,block1row4
Baer,block1row5
Assume that a separate index exists on the employee ID column. Conceptually, the index entries
might look as follows, with employee IDs distributed in almost random locations throughout the
two blocks:
100,block1row50
101,block2row1
102,block1row9
103,block2row19
104,block2row39
105,block1row4
Example 3-2 queries the ALL_INDEXES view for the clustering factor for these two indexes. The
clustering factor for EMP_NAME_IX is low, which means that adjacent index entries in a single leaf
block tend to point to rows in the same data blocks. The clustering factor for EMP_EMP_ID_PK is
high, which means that adjacent index entries in the same leaf block are much less likely to point
to rows in the same data blocks.
INDEX_NAME CLUSTERING_FACTOR
-------------------- -----------------
EMP_EMP_ID_PK 19
EMP_NAME_IX 2
A reverse key index is a type of B-tree index that physically reverses the bytes of each index
key while keeping the column order. For example, if the index key is 20, and if the two bytes
stored for this key in hexadecimal are C1,15 in a standard B-tree index, then a reverse key index
stores the bytes as 15,C1.
Reversing the key solves the problem of contention for leaf blocks in the right side of a B-tree
index. This problem can be especially acute in an Oracle Real Application Clusters (Oracle
RAC) database in which multiple instances repeatedly modify the same block. For example, in
an orders table the primary keys for orders are sequential. One instance in the cluster adds order
20, while another adds 21, with each instance writing its key to the same leaf block on the right-
hand side of the index.
In a reverse key index, the reversal of the byte order distributes inserts across all leaf keys in the
index. For example, keys such as 20 and 21 that would have been adjacent in a standard key
index are now stored far apart in separate blocks. Thus, I/O for insertions of sequential keys is
more evenly distributed.
Because the data in the index is not sorted by column key when it is stored, the reverse key
arrangement eliminates the ability to run an index range scanning query in some cases. For
example, if a user issues a query for order IDs greater than 20, then the database cannot start with
the block containing this ID and proceed horizontally through the leaf blocks.
In an ascending index, Oracle Database stores data in ascending order. By default, character
data is ordered by the binary values contained in each byte of the value, numeric data from
smallest to largest number, and date from earliest to latest value.
By specifying the DESC keyword in the CREATE INDEX statement, you can create a descending
index. In this case, the index stores data on a specified column or columns in descending order.
If the index in Figure 3-1 on the employees.department_id column were descending, then the
leaf blocking containing 250 would be on the left side of the tree and block with 0 on the right.
The default search through a descending index is from highest to lowest value.
Descending indexes are useful when a query sorts some columns ascending and others
descending. For an example, assume that you create a composite index on
the last_name and department_id columns as follows:
If a user queries hr.employees for last names in ascending order (A to Z) and department IDs in
descending order (high to low), then the database can use this index to retrieve the data and avoid
the extra step of sorting it.
Key Compression
Oracle Database can use key compression to compress portions of the primary key column
values in a B-tree index or an index-organized table. Key compression can greatly reduce the
space consumed by the index.
In general, index keys have two pieces, a grouping piece and a unique piece. Key compression
breaks the index key into a prefix entry, which is the grouping piece, and a suffix entry, which
is the unique or nearly unique piece. The database achieves compression by sharing the prefix
entries among the suffix entries in an index block.
By default, the prefix of a unique index consists of all key columns excluding the last one,
whereas the prefix of a nonunique index consists of all key columns. For example, suppose that
you create a composite index on the oe.orders table as follows:
online,0,AAAPvCAAFAAAAFaAAa
online,0,AAAPvCAAFAAAAFaAAg
online,0,AAAPvCAAFAAAAFaAAl
online,2,AAAPvCAAFAAAAFaAAm
online,3,AAAPvCAAFAAAAFaAAq
online,3,AAAPvCAAFAAAAFaAAt
online,0
AAAPvCAAFAAAAFaAAa
AAAPvCAAFAAAAFaAAg
AAAPvCAAFAAAAFaAAl
online,2
AAAPvCAAFAAAAFaAAm
online,3
AAAPvCAAFAAAAFaAAq
AAAPvCAAFAAAAFaAAt
Suffix entries form the compressed version of index rows. Each suffix entry references a prefix
entry, which is stored in the same index block as the suffix entry.
Alternatively, you could specify a prefix length when creating a compressed index. For example,
if you specified prefix length 1, then the prefix would be order_mode and the suffix would
be order_status,rowid. For the values, the index would factor out duplicate occurrences
of online as follows:
online
0,AAAPvCAAFAAAAFaAAa
0,AAAPvCAAFAAAAFaAAg
0,AAAPvCAAFAAAAFaAAl
2,AAAPvCAAFAAAAFaAAm
3,AAAPvCAAFAAAAFaAAq
3,AAAPvCAAFAAAAFaAAt
The index stores a specific prefix once per leaf block at most. Only keys in the leaf blocks of a
B-tree index are compressed. In the branch blocks the key suffix can be truncated, but the key is
not compressed.
Bitmap Indexes
In a bitmap index, the database stores a bitmap for each index key. In a conventional B-tree
index, one index entry points to a single row. In a bitmap index, each index key stores pointers to
multiple rows.
Bitmap indexes are primarily designed for data warehousing or environments in which queries
reference many columns in an ad hoc fashion. Situations that may call for a bitmap index
include:
• The indexed columns have low cardinality, that is, the number of distinct values is small
compared to the number of table rows.
• The indexed table is either read-only or not subject to significant modification by DML
statements.
For a data warehouse example, the sh.customers table has a cust_gender column with only
two possible values: M and F. Suppose that queries for the number of customers of a particular
gender are common. In this case, the customers.cust_gender column would be a candidate for
a bitmap index.
Each bit in the bitmap corresponds to a possible rowid. If the bit is set, then the row with the
corresponding rowid contains the key value. A mapping function converts the bit position to an
actual rowid, so the bitmap index provides the same functionality as a B-tree index although it
uses a different internal representation.
If the indexed column in a single row is updated, then the database locks the index key entry (for
example, M or F) and not the individual bit mapped to the updated row. Because a key points to
many rows, DML on indexed data typically locks all of these rows. For this reason, bitmap
indexes are not appropriate for many OLTP applications.
query of the sh.customers table. Some columns in this table are candidates for a bitmap index.
1 Kessel M
2 Koch F
3 Emmerson M
4 Hardy M
5 Gowen M
6 Charles single F
7 Ingram single F
7 rows selected.
Table illustrates the bitmap index for the cust_gender column output It consists of two separate
bitmaps, one for each gender.
M 1 0 1 1 1 0
F 0 1 0 0 0 1
A mapping function converts each bit in the bitmap to a rowid of the customers table. Each bit
value depends on the values of the corresponding row in the table. For example, the bitmap for
the M value contains a 1 as its first bit because the gender is M in the first row of
the customers table. The bitmap cust_gender='M' has a 0 for its the bits in rows 2, 6, and 7
because these rows do not contain M as their value.
An analyst investigating demographic trends of the customers may ask, "How many of our
female customers are single or divorced?" This question corresponds to the following SQL
query:
SELECT COUNT(*)
FROM customers
Bitmap indexes can process this query efficiently by counting the number of 1 values in the
resulting bitmap, as illustrated. To identify the customers who satisfy the criteria, Oracle
Database can use the resulting bitmap to access the table.
M 1 0 1 1 1
F 0 1 0 0 0
single 0 0 0 0 0
divorced 0 0 0 0 0
A bitmap join index is a bitmap index for the join of two or more tables. For each value in a
table column, the index stores the rowid of the corresponding row in the indexed table. In
contrast, a standard bitmap index is created on a single table.
A bitmap join index is an efficient means of reducing the volume of data that must be joined by
performing restrictions in advance. For an example of when a bitmap join index would be useful,
assume that users often query the number of employees with a particular job type. A typical
query might look as follows:
SELECT COUNT(*)
The preceding query would typically use an index on jobs.job_title to retrieve the rows
for Accountant and then the job ID, and an index on employees.job_id to find the matching
rows. To retrieve the data from the index itself rather than from a scan of the tables, you could
create a bitmap join index as follows:
ON employees (jobs.job_title)
As illustrated in Figure , the index key is jobs.job_title and the indexed table is employees.
ORDER BY job_title;
jobs.job_title employees.rowid
----------------------------------- ------------------
Accountant AAAQNKAAFAAAABSAAL
Accountant AAAQNKAAFAAAABSAAN
Accountant AAAQNKAAFAAAABSAAM
Accountant AAAQNKAAFAAAABSAAJ
Accountant AAAQNKAAFAAAABSAAK
In a data warehouse, the join condition is an equijoin (it uses the equality operator) between the
primary key columns of the dimension tables and the foreign key columns in the fact table.
Bitmap join indexes are sometimes much more efficient in storage than materialized join views
joins i, an alternative for materializing n advance.
Oracle Database uses a B-tree index structure to store bitmaps for each indexed key. For
example, if jobs.job_title is the key column of a bitmap index, then the index data is stored
in one B-tree. The individual bitmaps are stored in the leaf blocks.
Assume that the jobs.job_title column has unique values Shipping Clerk, Stock Clerk,
and several others. A bitmap index entry for this index has the following components:
Conceptually, an index leaf block in this index could contain entries as follows:
Shipping Clerk,AAAPzRAAFAAAABSABQ,AAAPzRAAFAAAABSABZ,0010000100
Shipping Clerk,AAAPzRAAFAAAABSABa,AAAPzRAAFAAAABSABh,010010
Stock Clerk,AAAPzRAAFAAAABSAAa,AAAPzRAAFAAAABSAAc,1001001100
Stock Clerk,AAAPzRAAFAAAABSAAd,AAAPzRAAFAAAABSAAt,0101001001
Stock Clerk,AAAPzRAAFAAAABSAAu,AAAPzRAAFAAAABSABz,100001
The same job title appears in multiple entries because the rowid range differs.
Assume that a session updates the job ID of one employee from Shipping Clerk to Stock
Clerk. In this case, the session requires exclusive access to the index key entry for the old value
(Shipping Clerk) and the new value (Stock Clerk). Oracle Database locks the rows pointed to
by these two entries—but not the rows pointed to by Accountant or any other key—until
the UPDATE commits.
The data for a bitmap index is stored in one segment. Oracle Database stores each bitmap in one
or more pieces. Each piece occupies part of a single data block.
Function-Based Indexes
You can create indexes on functions and expressions that involve one or more columns in the
table being indexed. A function-based index computes the value of a function or expression
involving one or more columns and stores it in the index. A function-based index can be either a
B-tree or a bitmap index.
The function used for building the index can be an arithmetic expression or an expression that
contains a SQL function, user-defined PL/SQL function, package function, or C callout. For
example, a function could add the values in two columns.
Function-based indexes are efficient for evaluating statements that contain functions in
their WHERE clauses. The database only uses the function-based index when the function is
included in a query. When the database processes INSERT and UPDATE statements, however, it
must still evaluate the function to process the statement.
FROM employees
ON employees ( UPPER(first_name) );
SELECT *
FROM employees
A function-based index is also useful for indexing only specific rows in a table. For example,
the cust_valid column in the sh.customers table has either I or A as a value. To index only
the A rows, you could write a function that returns a null value for any rows other than
the A rows. You could create the index as follows:
The optimizer can use an index range scan on a function-based index for queries with
expressions in WHERE clause. The range scan access path is especially beneficial when the
predicate (WHERE clause) has low selectivity. In Example the optimizer can use an index range
scan if an index is built on the expression 12*salary*commission_pct.
A virtual column is useful for speeding access to data derived from expressions. For example,
you could define virtual column annual_sal as 12*salary*commission_pct and create a
function-based index on annual_sal.
The optimizer performs expression matching by parsing the expression in a SQL statement and
then comparing the expression trees of the statement and the function-based index. This
comparison is case-insensitive and ignores blank spaces.
The application software, called the cartridge, controls the structure and content of a domain
index. The database interacts with the application to build, maintain, and search the domain
index. The index structure itself can be stored in the database as an index-organized table or
externally as a file.
Index Storage
Oracle Database stores index data in an index segment. Space available for index data in a data
block is the data block size minus block overhead, entry overhead, rowid, and one length byte
for each value indexed.
The tablespace of an index segment is either the default tablespace of the owner or a tablespace
specifically named in the CREATE INDEX statement. For ease of administration you can store an
index in a separate tablespace from its table. For example, you may choose not to back up
tablespaces containing only indexes, which can be rebuilt, and so decrease the time and storage
required for backups.
For an analogy of an index-organized table, suppose a human resources manager has a book case
of cardboard boxes. Each box is labeled with a number—1, 2, 3, 4, and so on—but the boxes do
not sit on the shelves in sequential order. Instead, each box contains a pointer to the shelf
location of the next box in the sequence.
Folders containing employee records are stored in each box. The folders are sorted by employee
ID. Employee King has ID 100, which is the lowest ID, so his folder is at the bottom of box 1.
The folder for employee 101 is on top of 100, 102 is on top of 101, and so on until box 1 is full.
The next folder in the sequence is at the bottom of box 2.
In this analogy, ordering folders by employee ID makes it possible to search efficiently for
folders without having to maintain a separate index. Suppose a user requests the records for
employees 107, 120, and 122. Instead of searching an index in one step and retrieving the folders
in a separate step, the manager can search the folders in sequential order and retrieve each folder
as found.
Index-organized tables provide faster access to table rows by primary key or a valid prefix of the
key. The presence of non-key columns of a row in the leaf block avoids an additional data
block I/O. For example, the salary of employee 100 is stored in the index row itself. Also,
because rows are stored in primary key order, range access by the primary key or prefix involves
minimal block I/Os. Another benefit is the avoidance of the space overhead of a separate primary
key index.
Index-organized tables are useful when related pieces of data must be stored together or data
must be physically stored in a specific order. This type of table is often used for information
retrieval, spatial (see "Overview of Oracle Spatial"), and OLAP applications (see "OLAP").
Index-Organized Table Characteristics
The database system performs all operations on index-organized tables by manipulating the B-
tree index structure. Table summarizes the differences between index-organized tables and
heap-organized tables.
Can contain a column of the LONG data type and columns of LOB data
types.
Figure illustrates the structure of an index-organized departments table. The leaf blocks
contain the rows of the table, ordered sequentially by primary key. For example, the first value in
the first leaf block shows a department ID of 20, department name of Marketing, manager ID
of 201, and location ID of 1800.
An index-organized table stores all data in the same structure and does not need to store the
rowid. As shown in Figure , leaf block 1 in an index-organized table might contain entries as
follows, ordered by primary key:
20,Marketing,201,1800
30,Purchasing,114,1700
50,Shipping,121,1500
60,IT,103,1400
A scan of the index-organized table rows in primary key order reads the blocks in the following
sequence:
1. Block 1
2. Block 2
50,Shipping,121,1500
20,Marketing,201,1800
30,Purchasing,114,1700
60,IT,103,1400
A B-tree index leaf block for this heap-organized table contains the following entries, where the
first value is the primary key and the second is the rowid:
20,AAAPeXAAFAAAAAyAAD
30,AAAPeXAAFAAAAAyAAA
50,AAAPeXAAFAAAAAyAAC
60,AAAPeXAAFAAAAAyAAB
A scan of the table rows in primary key order reads the table segment blocks in the following
sequence:
1. Block 1
2. Block 2
3. Block 1
4. Block 2
Thus, the number of block I/Os in this example is double the number in the index-organized
example.
When creating an index-organized table, you can specify a separate segment as a row overflow
area. In index-organized tables, B-tree index entries can be large because they contain an entire
row, so a separate segment to contain the entries is useful. In contrast, B-tree entries are usually
small because they consist of the key and rowid.
If a row overflow area is specified, then the database can divide a row in an index-organized
table into the following parts:
This part contains column values for all the primary key columns, a physical rowid that
points to the overflow part of the row, and optionally a few of the non-key columns. This
part is stored in the index segment.
This part contains column values for the remaining non-key columns. This part is stored
in the overflow storage area segment.
As explained in "Rowid Data Types", Oracle Database uses row identifiers called logical
rowids for index-organized tables. A logical rowid is a base64-encoded representation of the
table primary key. The logical rowid length depends on the primary key length.
Rows in index leaf blocks can move within or between blocks because of insertions. Rows in
index-organized tables do not migrate as heap-organized rows do (see "Chained and Migrated
Rows"). Because rows in index-organized tables do not have permanent physical addresses, the
database uses logical rowids based on primary key.
For example, assume that the departments table is index-organized. The location_id column
stores the ID of each department. The table stores rows as follows, with the last value as the
location ID:
10,Administration,200,1700
20,Marketing,201,1800
30,Purchasing,114,1700
40,Human Resources,203,2400
A secondary index on the location_id column might have index entries as follows, where the
value following the comma is the logical rowid:
1700,*BAFAJqoCwR/+
1700,*BAFAJqoCwQv+
1800,*BAFAJqoCwRX+
2400,*BAFAJqoCwSn+
Secondary indexes provide fast and efficient access to index-organized tables using columns that
are neither the primary key nor a prefix of the primary key. For example, a query of the names of
departments whose ID is greater than 1700 could use the secondary index to speed data access.
Secondary indexes use the logical rowids to locate table rows. A logical rowid includes
a physical guess, which is the physical rowid of the index entry when it was first made. Oracle
Database can use physical guesses to probe directly into the leaf block of the index-organized
table, bypassing the primary key search. When the physical location of a row changes, the logical
rowid remains valid even if it contains a physical guess that is stale.
For a heap-organized table, access by a secondary index involves a scan of the secondary index
and an additional I/O to fetch the data block containing the row. For index-organized tables,
access by a secondary index varies, depending on the use and accuracy of physical guesses:
• Without physical guesses, access involves two index scans: a scan of the secondary index
followed by a scan of the primary key index.
• With physical guesses, access depends on their accuracy:
o With accurate physical guesses, access involves a secondary index scan and an
additional I/O to fetch the data block containing the row.
o With inaccurate physical guesses, access involves a secondary index scan and an
I/O to fetch the wrong data block (as indicated by the guess), followed by an index
unique scan of the index organized table by primary key value.
When bitmap indexes exist on an index-organized table, all the bitmap indexes use a heap-
organized mapping table. The mapping table stores the logical rowids of the index-organized
table. Each mapping table row stores one logical rowid for the corresponding index-organized
table row.
The database accesses a bitmap index using a search key. If the database finds the key, then the
bitmap entry is converted to a physical rowid. With heap-organized tables, the database uses the
physical rowid to access the base table. With index-organized tables, the database uses the
physical rowid to access the mapping table, which in turn yields a logical rowid that the database
uses to access the index-organized table. Figure 3-4 illustrates index access for a query of
the departments_iot table.
Figure 3-4 Bitmap Index on Index-Organized Table