Rdbms Final-Notes PDF
Rdbms Final-Notes PDF
RDBMSes store data in the form of tables, with most commercial relational
database management systems using Structured Query Language (SQL) to access
the database. However, since SQL was invented after the initial development of the
relational model, it is not necessary for RDBMS use.
The RDBMS is the most popular database system among organizations across the
world. It provides a dependable method of storing and retrieving large amounts of
data while offering a combination of system performance and ease of
implementation.
In general, databases store sets of data that can be queried for use in other
applications. A database management system supports the development,
administration and use of database platforms.
Number of allowed users. While a DBMS can only accept one user at a time,
an RDBMS can operate with multiple users.
Amount of data. RDBMSes can handle any amount of data, from small to
large, while a DBMS can only manage small amounts.
What is a field?
Every table is broken up into smaller entities called fields. The fields in the
CUSTOMERS table consist of ID, NAME, AGE, ADDRESS and SALARY.
A record is also called as a row of data is each individual entry that exists in a
table. For example, there are 7 records in the above CUSTOMERS table.
Following is a single row of data or record in the CUSTOMERS table −
+----+----------+-----+-----------+----------+
+----+----------+-----+-----------+----------+
What is a column?
A column is a vertical entity in a table that contains all information associated with
a specific field in a table.
+-----------+
| ADDRESS |
+-----------+
| Ahmedabad |
| Delhi |
| Kota |
| Mumbai |
| Bhopal |
| MP |
| Indore |
+----+------+
A NULL value in a table is a value in a field that appears to be blank, which means
a field with a NULL value is a field with no value.
It is very important to understand that a NULL value is different than a zero value
or a field that contains spaces. A field with a NULL value is the one that has been
left blank during a record creation.
SQL Constraints
Constraints are the rules enforced on data columns on a table. These are used to
limit the type of data that can go into a table. This ensures the accuracy and
reliability of the data in the database.
Constraints can either be column level or table level. Column level constraints are
applied only to one column whereas, table level constraints are applied to the entire
table.
Following are some of the most commonly used constraints available in SQL −
NOT NULL Constraint − Ensures that a column cannot have a NULL value.
UNIQUE Constraint − Ensures that all the values in a column are different.
INDEX − Used to create and retrieve data from the database very quickly.
Data Integrity
Database Normalization
Eliminating redundant data, for example, storing the same data in more than
one table.
Both these reasons are worthy goals as they reduce the amount of space a database
consumes and ensures that data is logically stored. Normalization consists of a
series of guidelines that help guide you in creating a good database structure.
Normalization guidelines are divided into normal forms; think of a form as the
format or the way a database structure is laid out. The aim of normal forms is to
organize the database structure, so that it complies with the rules of first normal
form, then second normal form and finally the third normal form.
It is your choice to take it further and go to the fourth normal form, fifth normal
form and so on, but in general, the third normal form is more than enough.
Unit 2 : 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. Following are certain notable facts about PL/SQL −
Direct call can also be made from external programming language calls to
database.
Features of PL/SQL
Advantages of PL/SQL
In this chapter, we will discuss the Basic Syntax of PL/SQL which is a block-
structured language; this means that the PL/SQL programs are divided and written
in logical blocks of code. Each block consists of three sub-parts −
Declarations
1 This section starts with the keyword DECLARE. It is an optional section and
defines all variables, cursors, subprograms, and other elements to be used in
the program.
Executable Commands
This section is enclosed between the keywords BEGIN and END and it is a
2 mandatory section. It consists of the executable PL/SQL statements of the
program. It should have at least one executable line of code, which may be
just a NULL command to indicate that nothing should be executed.
Exception Handling
3 This section starts with the keyword EXCEPTION. This optional section
contains exception(s) that handle errors in the program.
Every PL/SQL statement ends with a semicolon (;). PL/SQL blocks can be nested
within other PL/SQL blocks using BEGIN and END. Following is the basic
structure of a PL/SQL block −
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
<exception handling>
END;
DECLARE
BEGIN
dbms_output.put_line(message);
END;
The end; line signals the end of the PL/SQL block. To run the code from the SQL
command line, you may need to type / at the beginning of the first blank line after
the last line of the code. When the above code is executed at the SQL prompt, it
produces the following result −
Hello World
Delimiter Description
% Attribute indicator
. Component selector
, Item separator
= Relational operator
; Statement terminator
:= Assignment operator
|| Concatenation operator
** Exponentiation operator
.. Range operator
Program comments are explanatory statements that can be included in the PL/SQL
code that you write and helps anyone reading its source code. All programming
languages allow some form of comments.
DECLARE
-- variable declaration
BEGIN
/*
*/
dbms_output.put_line(message);
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Hello World
PL/SQL block
Function
Package
Package body
Procedure
Trigger
Type
Type body
Data Types
he PL/SQL variables, constants and parameters must have a valid data type, which
specifies a storage format, constraints, and a valid range of values. We will focus
on the SCALAR and the LOB data types in this chapter. The other two data types
will be covered in other chapters.
Scalar
1 Single values with no internal components, such as a NUMBER,
DATE, or BOOLEAN.
2 Pointers to large objects that are stored separately from other data
items, such as text, graphic images, video clips, and sound
waveforms.
Composite
3 Data items that have internal components that can be accessed
individually. For example, collections and records.
Reference
4
Pointers to other data items.
PL/SQL Scalar Data Types and Subtypes come under the following categories −
Numeric
1
Numeric values on which arithmetic operations are performed.
Character
2 Alphanumeric values that represent single characters or strings of
characters.
Boolean
3
Logical values on which logical operations are performed.
Datetime
4
Dates and times.
PL/SQL provides subtypes of data types. For example, the data type NUMBER has
a subtype called INTEGER. You can use the subtypes in your PL/SQL program to
make the data types compatible with data types in other programs while
embedding the PL/SQL code in another program, such as a Java program.
Following table lists out the PL/SQL pre-defined numeric data types and their sub-
types −
PLS_INTEGER
1 Signed integer in range -2,147,483,648 through 2,147,483,647, represented
in 32 bits
BINARY_INTEGER
2 Signed integer in range -2,147,483,648 through 2,147,483,647, represented
in 32 bits
BINARY_FLOAT
3
Single-precision IEEE 754-format floating-point number
BINARY_DOUBLE
4
Double-precision IEEE 754-format floating-point number
NUMBER(prec, scale)
5 Fixed-point or floating-point number with absolute value in range 1E-130 to
(but not including) 1.0E126. A NUMBER variable can also represent 0
DEC(prec, scale)
6
ANSI specific fixed-point type with maximum precision of 38 decimal digits
DECIMAL(prec, scale)
7
IBM specific fixed-point type with maximum precision of 38 decimal digits
8 NUMERIC(pre, secale)
DOUBLE PRECISION
9 ANSI specific floating-point type with maximum precision of 126 binary
digits (approximately 38 decimal digits)
FLOAT
10 ANSI and IBM specific floating-point type with maximum precision of 126
binary digits (approximately 38 decimal digits)
INT
11
ANSI specific integer type with maximum precision of 38 decimal digits
INTEGER
12 ANSI and IBM specific integer type with maximum precision of 38 decimal
digits
SMALLINT
13 ANSI and IBM specific integer type with maximum precision of 38 decimal
digits
REAL
14 Floating-point type with maximum precision of 63 binary digits
(approximately 18 decimal digits)
DECLARE
num1 INTEGER;
num2 REAL;
BEGIN
null;
END;
When the above code is compiled and executed, it produces the following result −
Following is the detail of PL/SQL pre-defined character data types and their sub-
types −
CHAR
1
Fixed-length character string with maximum size of 32,767 bytes
VARCHAR2
2
Variable-length character string with maximum size of 32,767 bytes
RAW
3 Variable-length binary or byte string with maximum size of 32,767
bytes, not interpreted by PL/SQL
NCHAR
4 Fixed-length national character string with maximum size of 32,767
bytes
NVARCHAR2
5 Variable-length national character string with maximum size of
32,767 bytes
LONG
6
Variable-length character string with maximum size of 32,760 bytes
LONG RAW
7 Variable-length binary or byte string with maximum size of 32,760
bytes, not interpreted by PL/SQL
ROWID
8
Physical row identifier, the address of a row in an ordinary table
UROWID
9
Universal row identifier (physical, logical, or foreign row identifier)
The BOOLEAN data type stores logical values that are used in logical operations.
The logical values are the Boolean values TRUE and FALSE and the value NULL.
SQL statements
The DATE datatype is used to store fixed-length datetimes, which include the time
of day in seconds since midnight. Valid dates range from January 1, 4712 BC to
December 31, 9999 AD.
Each DATE includes the century, year, month, day, hour, minute, and second. The
following table shows the valid values for each field −
MONTH 01 to 12 0 to 11
HOUR 00 to 23 0 to 23
MINUTE 00 to 59 0 to 59
Large Object (LOB) data types refer to large data items such as text, graphic
images, video clips, and sound waveforms. LOB data types allow efficient,
random, piecewise access to this data. Following are the predefined PL/SQL LOB
data types –
A subtype is a subset of another data type, which is called its base type. A subtype
has the same valid operations as its base type, but only a subset of its valid values.
You can define and use your own subtypes. The following program illustrates
defining and using a user-defined subtype −
DECLARE
salutation name;
greetings message;
BEGIN
END;
When the above code is executed at the SQL prompt, it produces the following
result −
NULLs in PL/SQL
PL/SQL NULL values represent missing or unknown data and they are not an
integer, a character, or any other specific data type. Note that NULL is not the
same as an empty data string or the null character value '\0'. A null can be assigned
but it cannot be equated with anything, including itself.
variable
A variable is nothing but a name given to a storage area that our programs can
manipulate. Each variable in PL/SQL has a specific data type, which determines
the size and the layout of the variable's memory; the range of values that can be
stored within that memory and the set of operations that can be applied to the
variable.
name varchar2(25);
address varchar2(100);
When you provide a size, scale or precision limit with the data type, it is called
a constrained declaration. Constrained declarations require less memory than
unconstrained declarations. For example −
name varchar2(25);
address varchar2(100);
For example −
counter binary_integer := 0;
You can also specify that a variable should not have a NULL value using the NOT
NULL constraint. If you use the NOT NULL constraint, you must explicitly assign
an initial value for that variable.
DECLARE
a integer := 10;
b integer := 20;
c integer;
f real;
BEGIN
c := a + b;
f := 70.0/3.0;
END;
Value of c: 30
Value of f: 23.333333333333333333
PL/SQL allows the nesting of blocks, i.e., each program block may contain another
inner block. If a variable is declared within an inner block, it is not accessible to
the outer block. However, if a variable is declared and accessible to an outer block,
it is also accessible to all nested inner blocks. There are two types of variable scope
−
Following example shows the usage of Local and Global variables in its simple
form −
DECLARE
-- Global variables
BEGIN
DECLARE
-- Local variables
BEGIN
END;
END;
You can use the SELECT INTO statement of SQL to assign values to PL/SQL
variables. For each item in the SELECT list, there must be a corresponding, type-
compatible variable in the INTO list. The following example illustrates the
concept. Let us create a table named CUSTOMERS −
);
Table Created
The following program assigns values from the above table to PL/SQL variables
using the SELECT INTO clause of SQL −
DECLARE
c_id customers.id%type := 1;
c_name customers.name%type;
c_addr customers.address%type;
c_sal customers.salary%type;
BEGIN
FROM customers
WHERE id = c_id;
dbms_output.put_line
('Customer ' ||c_name || ' from ' || c_addr || ' earns ' || c_sal);
END;
A constant holds a value that once declared, does not change in the program. A
constant declaration specifies its name, data type, and value, and allocates storage
for it. The declaration can also impose the NOT NULL constraint.
Declaring a Constant
DECLARE
-- constant declaration
-- other declarations
radius number(5,2);
dia number(5,2);
BEGIN
-- processing
radius := 9.5;
dia := radius * 2;
-- output
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Radius: 9.5
Diameter: 19
Circumference: 59.69
Area: 283.53
Numeric Literals
Character Literals
String Literals
BOOLEAN Literals
The following table provides examples from all these categories of literal values.
Numeric Literals
Character Literals
2
'A' '%' '9' ' ' 'z' '('
String Literals
'Hello, world!'
3
'Tutorials Point'
'19-NOV-12'
BOOLEAN Literals
4
TRUE, FALSE, and NULL.
5 DATE '1978-12-25';
To embed single quotes within a string literal, place two single quotes next to each
other as shown in the following program −
DECLARE
BEGIN
dbms_output.put_line(message);
END;
When the above code is executed at the SQL prompt, it produces the following
result −
That's tutorialspoint.com!
operators in PL/SQL
Arithmetic operators
Relational operators
Comparison operators
Logical operators
String operators
Arithmetic Operators
Following table shows all the arithmetic operators supported by PL/SQL. Let us
assume variable A holds 10 and variable B holds 5, then −
Show Examples
Relational Operators
Show Examples
!=
Checks if the values of two operands are equal or not, (A != B) is
<>
if values are not equal then condition becomes true. true.
~=
Checks if the value of left operand is less than the value (A < B) is
<
of right operand, if yes then condition becomes true. true.
Comparison Operators
Comparison operators are used for comparing one expression to another. The result
is always either TRUE, FALSE or NULL.
Show Examples
If x = 10 then, x
The BETWEEN operator tests between 5 and 20
whether a value lies in a specified returns true, x between
BETWEEN
range. x BETWEEN a AND b 5 and 10 returns true,
means that x >= a and x <= b. but x between 11 and
20 returns false.
Logical Operators
Following table shows the Logical operators supported by PL/SQL. All these
operators work on Boolean operands and produce Boolean results. Let us
assume variable A holds true and variable B holds false, then −
Show Examples
(A and B) is
and Called the logical AND operator. If both the operands
Called the logical NOT Operator. Used to reverse the not (A and
not logical state of its operand. If a condition is true then B) is true.
Logical NOT operator will make it false.
Here, operators with the highest precedence appear at the top of the table, those
with the lowest appear at the bottom. Within an expression, higher precedence
operators will be evaluated first.
The precedence of operators goes as follows: =, <, >, <=, >=, <>, !=, ~=, ^=, IS
NULL, LIKE, BETWEEN, IN.
Show Examples
Operator Operation
** exponentiation
+, - identity, negation
*, / multiplication, division
comparison
AND conjunction
OR inclusion
Creating a Function
RETURN return_datatype
{IS | AS}
BEGIN
END [function_name];
Where,
The optional parameter list contains name, mode and types of the
parameters. IN represents the value that will be passed from outside and
OUT represents the parameter that will be used to return a value outside of
the procedure.
The RETURN clause specifies the data type you are going to return from the
function.
Example
The following example illustrates how to create and call a standalone function.
This function returns the total number of CUSTOMERS in the customers table.
We will use the CUSTOMERS table, which we had created in the PL/SQL
Variables chapter −
+----+----------+-----+-----------+----------+
+----+----------+-----+-----------+----------+
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
RETURN number IS
total number(2) := 0;
BEGIN
FROM customers;
RETURN total;
END;
When the above code is executed using the SQL prompt, it will produce the
following result −
Function created.
Calling a Function
While creating a function, you give a definition of what the function has to do. To
use a function, you will have to call that function to perform the defined task.
When a program calls a function, the program control is transferred to the called
function.
A called function performs the defined task and when its return statement is
executed or when the last end statement is reached, it returns the program control
back to the main program.
To call a function, you simply need to pass the required parameters along with the
function name and if the function returns a value, then you can store the returned
value. Following program calls the function totalCustomers from an anonymous
block −
DECLARE
c number(2);
BEGIN
c := totalCustomers();
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Example
DECLARE
a number;
b number;
c number;
RETURN number
IS
z number;
BEGIN
IF x > y THEN
z:= x;
ELSE
Z:= y;
END IF;
RETURN z;
END;
BEGIN
a:= 23;
b:= 45;
c := findMax(a, b);
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Maximum of (23,45): 45
We have seen that a program or subprogram may call another subprogram. When a
subprogram calls itself, it is referred to as a recursive call and the process is known
as recursion.
n! = n*(n-1)!
= n*(n-1)*(n-2)!
...
= n*(n-1)*(n-2)*(n-3)... 1
The following program calculates the factorial of a given number by calling itself
recursively −
DECLARE
num number;
factorial number;
RETURN number
IS
f number;
BEGIN
IF x=0 THEN
f := 1;
ELSE
f := x * fact(x-1);
END IF;
RETURN f;
END;
BEGIN
num:= 6;
factorial := fact(num);
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Factorial 6 is 720
Inside a package
PL/SQL subprograms are named PL/SQL blocks that can be invoked with a set of
parameters. PL/SQL provides two kinds of subprograms −
Each PL/SQL subprogram has a name, and may also have a parameter list. Like
anonymous PL/SQL blocks, the named blocks will also have the following three
parts −
Declarative Part
Executable Part
2 This is a mandatory part and contains statements that perform
the designated action.
Exception-handling
3 This is again an optional part. It contains the code that handles
run-time errors.
Creating a Procedure
{IS | AS}
BEGIN
END procedure_name;
Where,
The optional parameter list contains name, mode and types of the
parameters. IN represents the value that will be passed from outside and
OUT represents the parameter that will be used to return a value outside of
the procedure.
Example
The following example creates a simple procedure that displays the string 'Hello
World!' on the screen when executed.
AS
BEGIN
dbms_output.put_line('Hello World!');
END;
When the above code is executed using the SQL prompt, it will produce the
following result −
Procedure created.
The above procedure named 'greetings' can be called with the EXECUTE keyword
as −
EXECUTE greetings;
Hello World
BEGIN
greetings;
END;
Hello World
You can drop the greetings procedure by using the following statement −
The following table lists out the parameter modes in PL/SQL subprograms −
IN
OUT
IN OUT
This program finds the minimum of two values. Here, the procedure takes two
numbers using the IN mode and returns their minimum using the OUT parameters.
DECLARE
a number;
b number;
c number;
BEGIN
IF x < y THEN
z:= x;
ELSE
z:= y;
END IF;
END;
BEGIN
a:= 23;
b:= 45;
findMin(a, b, c);
END;
When the above code is executed at the SQL prompt, it produces the following
result −
This procedure computes the square of value of a passed value. This example
shows how we can use the same parameter to accept a value and then return
another result.
DECLARE
a number;
BEGIN
x := x * x;
END;
BEGIN
a:= 23;
squareNum(a);
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Positional notation
Named notation
Mixed notation
Positional Notation
findMin(a, b, c, d);
In positional notation, the first actual parameter is substituted for the first formal
parameter; the second actual parameter is substituted for the second formal
parameter, and so on. So, a is substituted for x, b is substituted for y, c is
substituted for z and d is substituted for m.
Named Notation
In named notation, the actual parameter is associated with the formal parameter
using the arrow symbol ( => ). The procedure call will be like the following −
Mixed Notation
In mixed notation, you can mix both notations in procedure call; however, the
positional notation should precede the named notation.
An array is a part of collection type data and it stands for variable-size arrays. We
will study other collection types in a later chapter 'PL/SQL Collections'.
Each element in a varray has an index associated with it. It also has a maximum
size that can be changed dynamically.
A varray type is created with the CREATE TYPE statement. You must specify the
maximum size and the type of elements stored in the varray.
The basic syntax for creating a VARRAY type at the schema level is −
Where,
Maximum size of a varray can be changed using the ALTER TYPE statement.
For example,
Type created.
The basic syntax for creating a VARRAY type within a PL/SQL block is −
For example −
Example 1
DECLARE
names namesarray;
marks grades;
total integer;
BEGIN
total := names.count;
END LOOP;
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Total 5 Students
Please note −
You can initialize the varray elements using the constructor method of the
varray type, which has the same name as the varray.
Example 2
+----+----------+-----+-----------+----------+
+----+----------+-----+-----------+----------+
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
Following example makes the use of cursor, which you will study in detail in a
separate chapter.
DECLARE
CURSOR c_customers is
BEGIN
counter := counter + 1;
name_list.extend;
name_list(counter) := n.name;
dbms_output.put_line('Customer('||counter ||'):'||name_list(counter));
END LOOP;
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
A cursor is a pointer to this context area. PL/SQL controls the context area through
a cursor. A cursor holds the rows (one or more) returned by a SQL statement. The
set of rows the cursor holds is referred to as the active set.
You can name a cursor so that it could be referred to in a program to fetch and
process the rows returned by the SQL statement, one at a time. There are two types
of cursors −
Implicit cursors
Explicit cursors
Implicit Cursors
In PL/SQL, you can refer to the most recent implicit cursor as the SQL cursor,
which always has attributes such as %FOUND, %ISOPEN, %NOTFOUND,
and %ROWCOUNT. The SQL cursor has additional
attributes, %BULK_ROWCOUNT and %BULK_EXCEPTIONS, designed for use
with the FORALL statement. The following table provides the description of the
most used attributes −
%FOUND
1
Returns TRUE if an INSERT, UPDATE, or DELETE statement affected one or more
rows or a SELECT INTO statement returned one or more rows. Otherwise, it returns
FALSE.
%NOTFOUND
%ISOPEN
3 Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor
automatically after executing its associated SQL statement.
%ROWCOUNT
4 Returns the number of rows affected by an INSERT, UPDATE, or DELETE
statement, or returned by a SELECT INTO statement.
Example
We will be using the CUSTOMERS table we had created and used in the previous
chapters.
+----+----------+-----+-----------+----------+
+----+----------+-----+-----------+----------+
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
The following program will update the table and increase the salary of each
customer by 500 and use the SQL%ROWCOUNT attribute to determine the
number of rows affected −
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
IF sql%notfound THEN
total_rows := sql%rowcount;
END IF;
END;
When the above code is executed at the SQL prompt, it produces the following
result −
6 customers selected
If you check the records in customers table, you will find that the rows have been
updated −
+----+----------+-----+-----------+----------+
+----+----------+-----+-----------+----------+
| 6 | Komal | 22 | MP | 5000.00 |
+----+----------+-----+-----------+----------+
Explicit Cursors
Explicit cursors are programmer-defined cursors for gaining more control over
the context area. An explicit cursor should be defined in the declaration section of
the PL/SQL Block. It is created on a SELECT Statement which returns more than
one row.
Declaring the cursor defines the cursor with a name and the associated SELECT
statement. For example −
CURSOR c_customers IS
Opening the cursor allocates the memory for the cursor and makes it ready for
fetching the rows returned by the SQL statement into it. For example, we will open
the above defined cursor as follows −
OPEN c_customers;
Fetching the cursor involves accessing one row at a time. For example, we will
fetch rows from the above-opened cursor as follows −
Closing the cursor means releasing the allocated memory. For example, we will
close the above-opened cursor as follows −
CLOSE c_customers;
Example
DECLARE
c_id customers.id%type;
c_name customer.name%type;
c_addr customers.address%type;
CURSOR c_customers is
BEGIN
OPEN c_customers;
LOOP
END LOOP;
CLOSE c_customers;
END;
When the above code is executed at the SQL prompt, it produces the following
result −
1 Ramesh Ahmedabad
2 Khilan Delhi
3 kaushik Kota
4 Chaitali Mumbai
5 Hardik Bhopal
6 Komal MP
System-defined exceptions
User-defined exceptions
The general syntax for exception handling is as follows. Here you can list down as
many exceptions as you can handle. The default exception will be handled
using WHEN others THEN −
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
exception1-handling-statements
exception2-handling-statements
exception3-handling-statements
........
exception3-handling-statements
END;
Example
Let us write a 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 the 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 in
the EXCEPTION 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 for raising an
exception −
DECLARE
exception_name EXCEPTION;
BEGIN
IF condition THEN
RAISE exception_name;
END IF;
EXCEPTION
statement;
END;
You can use the above syntax in raising the Oracle standard exception or any user-
defined exception. In the next section, we will give you an example on raising a
user-defined exception. You can raise the Oracle standard exceptions in a similar
way.
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;
END IF;
EXCEPTION
dbms_output.put_line('Error!');
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Pre-defined Exceptions
PL/SQL provides many pre-defined exceptions, which are executed when any
database rule is violated by a program. For example, the predefined exception
NO_DATA_FOUND is raised when a SELECT INTO statement returns no rows.
The following table lists few of the important pre-defined exceptions −
Oracle
Exception SQLCODE Description
Error
It is raised when a
program attempts to
apply collection methods
other than EXISTS to an
uninitialized nested table
COLLECTION_IS_NULL 06531 -6531
or varray, or the program
attempts to assign values
to the elements of an
uninitialized nested table
or varray.
It is raised when
duplicate values are
DUP_VAL_ON_INDEX 00001 -1 attempted to be stored in
a column with unique
index.
It is raised when
attempts are made to
make a cursor operation
INVALID_CURSOR 01001 -1001
that is not allowed, such
as closing an unopened
cursor.
It is raised when a
program attempts to log
LOGIN_DENIED 01017 -1017 on to the database with
an invalid username or
password.
It is raised when a
SELECT INTO
NO_DATA_FOUND 01403 +100
statement returns no
rows.
It is raised when a
database call is issued
NOT_LOGGED_ON 01012 -1012
without being connected
to the database.
It is raised when
PROGRAM_ERROR 06501 -6501 PL/SQL has an internal
problem.
It is raised when a
member method is
SELF_IS_NULL 30625 -30625 invoked, but the instance
of the object type was
not initialized.
It is raised when
PL/SQL ran out of
STORAGE_ERROR 06500 -6500
memory or memory was
corrupted.
It is raised when a
SELECT INTO
TOO_MANY_ROWS 01422 -1422
statement returns more
than one row.
It is raised when an
arithmetic, conversion,
VALUE_ERROR 06502 -6502 truncation, or
sizeconstraint error
occurs.
It is raised when an
ZERO_DIVIDE 01476 1476 attempt is made to divide
a number by zero.
Triggers
Triggers are stored programs, which are automatically executed or fired when
some events occur. Triggers are, in fact, written to be executed in response to any
of the following events −
Triggers can be defined on the table, view, schema, or database with which the
event is associated.
Benefits of Triggers
Auditing
Creating Triggers
[OF col_name]
ON table_name
WHEN (condition)
DECLARE
Declaration-statements
BEGIN
Executable-statements
EXCEPTION
Exception-handling-statements
END;
Where,
{BEFORE | AFTER | INSTEAD OF} − This specifies when the trigger will
be executed. The INSTEAD OF clause is used for creating trigger on a view.
[OF col_name] − This specifies the column name that will be updated.
[ON table_name] − This specifies the name of the table associated with the
trigger.
[FOR EACH ROW] − This specifies a row-level trigger, i.e., the trigger will
be executed for each row being affected. Otherwise the trigger will execute
just once when the SQL statement is executed, which is called a table level
trigger.
WHEN (condition) − This provides a condition for rows for which the
trigger would fire. This clause is valid only for row-level triggers.
Example
To start with, we will be using the CUSTOMERS table we had created and used in
the previous chapters −
+----+----------+-----+-----------+----------+
+----+----------+-----+-----------+----------+
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
The following program creates a row-level trigger for the customers table that
would fire for INSERT or UPDATE or DELETE operations performed on the
CUSTOMERS table. This trigger will display the salary difference between the old
values and new values −
DECLARE
sal_diff number;
BEGIN
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Trigger created.
OLD and NEW references are not available for table-level triggers, rather
you can use them for record-level triggers.
If you want to query the table in the same trigger, then you should use the
AFTER keyword, because triggers can query the table or change it again
only after the initial changes are applied and the table is back in a consistent
state.
The above trigger has been written in such a way that it will fire before any
DELETE or INSERT or UPDATE operation on the table, but you can write
your trigger on a single or multiple operations, for example BEFORE
DELETE, which will fire whenever a record will be deleted using the
DELETE operation on the table.
Triggering a Trigger
Let us perform some DML operations on the CUSTOMERS table. Here is one
INSERT statement, which will create a new record in the table −
Old salary:
Salary difference:
Because this is a new record, old salary is not available and the above result comes
as null. Let us now perform one more DML operation on the CUSTOMERS table.
The UPDATE statement will update an existing record in the table −
UPDATE customers
WHERE id = 2;
conditions in PL/SQL
IF - THEN statement
IF-THEN-ELSE statement
IF-THEN-ELSIF statement
3
It allows you to choose between several alternatives.
Case statement
nested IF-THEN-ELSE
6 You can use one IF-THEN or IF-THEN-ELSIF statement inside
another IF-THEN or IF-THEN-ELSIF statement(s).
Loops in PL/SQL.
here may be a situation when you need to execute a block of code several number
of times. In general, statements are executed sequentially: The first statement in a
function is executed first, followed by the second, and so on.
Programming languages provide various control structures that allow for more
complicated execution paths.
PL/SQL provides the following types of loop to handle the looping requirements.
Click the following links to check their detail.
PL/SQL loops can be labeled. The label should be enclosed by double angle
brackets (<< and >>) and appear at the beginning of the LOOP statement. The
label name can also appear at the end of the LOOP statement. You may use the
label in the EXIT statement to exit from the loop.
DECLARE
i number(1);
j number(1);
BEGIN
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Loop control statements change execution from its normal sequence. When
execution leaves a scope, all automatic objects that were created in that scope are
destroyed.
PL/SQL supports the following control statements. Labeling loops also help in
taking the control outside a loop. Click the following links to check their details.
EXIT statement
1 The Exit statement completes the loop and control passes to the statement
immediately after the END LOOP.
CONTINUE statement
2 Causes the loop to skip the remainder of its body and immediately retest
its condition prior to reiterating.
GOTO statement
3 Transfers control to the labeled statement. Though it is not advised to use
the GOTO statement in your program.
string in PL/SQL
Character large objects (CLOBs) − These are variable-length strings that can
be up to 128 terabytes.
To include a single quote inside a string literal, you need to type two single quotes
next to one another. For example,
If you need to declare a variable-length string, you must provide the maximum
length of that string. For example, the VARCHAR2 data type. The following
example illustrates declaring and using some string variables −
DECLARE
name varchar2(20);
company varchar2(30);
introduction clob;
choice char(1);
BEGIN
company := 'Infotech';
choice := 'y';
dbms_output.put_line(name);
dbms_output.put_line(company);
dbms_output.put_line(introduction);
END IF;
END;
When the above code is executed at the SQL prompt, it produces the following
result −
John Smith
Infotech
To declare a fixed-length string, use the CHAR datatype. Here you do not have to
specify a maximum length for a fixed-length variable. If you leave off the length
constraint, Oracle Database automatically uses a maximum length required. The
following two declarations are identical −
PL/SQL offers the concatenation operator (||) for joining two strings. The
following table provides the string functions provided by PL/SQL −
ASCII(x);
1
Returns the ASCII value of the character x.
CHR(x);
2
Returns the character with the ASCII value of x.
CONCAT(x, y);
3
Concatenates the strings x and y and returns the appended string.
INITCAP(x);
4 Converts the initial letter of each word in x to uppercase and returns that
string.
INSTRB(x);
6 Returns the location of a string within another string, but returns the
value in bytes.
LENGTH(x);
7
Returns the number of characters in x.
LENGTHB(x);
8 Returns the length of a character string in bytes for single byte character
set.
LOWER(x);
9
Converts the letters in x to lowercase and returns that string.
LTRIM(x [, trim_string]);
11
Trims characters from the left of x.
NANVL(x, value);
12 Returns value if x matches the NaN special value (not a number),
otherwise x is returned.
NLS_INITCAP(x);
13 Same as the INITCAP function except that it can use a different sort
method as specified by NLSSORT.
NLS_LOWER(x) ;
14 Same as the LOWER function except that it can use a different sort
method as specified by NLSSORT.
NLS_UPPER(x);
15 Same as the UPPER function except that it can use a different sort
method as specified by NLSSORT.
NLSSORT(x);
16 Changes the method of sorting the characters. Must be specified before
any NLS function; otherwise, the default sort will be used.
NVL(x, value);
17
Returns value if x is null; otherwise, x is returned.
RTRIM(x [, trim_string]);
21
Trims x from the right.
SOUNDEX(x) ;
22
Returns a string containing the phonetic representation of x.
SUBSTRB(x);
24 Same as SUBSTR except that the parameters are expressed in bytes
instead of characters for the single-byte character systems.
UPPER(x);
26
Converts the letters in x to uppercase and returns that string.
Example 1
DECLARE
BEGIN
dbms_output.put_line(UPPER(greetings));
dbms_output.put_line(LOWER(greetings));
dbms_output.put_line(INITCAP(greetings));
END;
When the above code is executed at the SQL prompt, it produces the following
result −
HELLO WORLD
hello world
Hello World
World
ello World
Example 2
DECLARE
BEGIN
dbms_output.put_line(RTRIM(greetings,'.'));
dbms_output.put_line(LTRIM(greetings, '.'));
END;
When the above code is executed at the SQL prompt, it produces the following
result −
......Hello World
Hello World.....
Hello World
Packages in PL/SQL
Packages are schema objects that groups logically related PL/SQL types, variables,
and subprograms.
Package specification
Package Specification
The specification is the interface to the package. It just DECLARES the types,
variables, constants, exceptions, cursors, and subprograms that can be referenced
from outside the package. In other words, it contains all information about the
content of the package, but excludes the code for the subprograms.
All objects placed in the specification are called public objects. Any subprogram
not in the package specification but coded in the package body is called
a private object.
END cust_sal;
When the above code is executed at the SQL prompt, it produces the following
result −
Package created.
Package Body
The package body has the codes for various methods declared in the package
specification and other private declarations, which are hidden from the code
outside the package.
The CREATE PACKAGE BODY Statement is used for creating the package body.
The following code snippet shows the package body declaration for
the cust_sal package created above. I assumed that we already have CUSTOMERS
table created in our database as mentioned in the PL/SQL - Variables chapter.
c_sal customers.salary%TYPE;
BEGIN
FROM customers
WHERE id = c_id;
END find_sal;
END cust_sal;
When the above code is executed at the SQL prompt, it produces the following
result −
The package elements (variables, procedures or functions) are accessed with the
following syntax −
package_name.element_name;
Consider, we already have created the above package in our database schema, the
following program uses the find_sal method of the cust_sal package −
DECLARE
BEGIN
cust_sal.find_sal(code);
END;
When the above code is executed at the SQL prompt, it prompts to enter the
customer ID and when you enter an ID, it displays the corresponding salary as
follows −
Salary: 3000
Example
The following program provides a more complete package. We will use the
CUSTOMERS table stored in our database with the following records −
+----+----------+-----+-----------+----------+
+----+----------+-----+-----------+----------+
| 6 | Komal | 22 | MP | 5500.00 |
+----+----------+-----+-----------+----------+
-- Adds a customer
c_name customerS.No.ame%type,
c_age customers.age%type,
c_addr customers.address%type,
c_sal customers.salary%type);
-- Removes a customer
PROCEDURE listCustomer;
END c_package;
When the above code is executed at the SQL prompt, it creates the above package
and displays the following result −
Package created.
c_name customerS.No.ame%type,
c_age customers.age%type,
c_addr customers.address%type,
c_sal customers.salary%type)
IS
BEGIN
END addCustomer;
BEGIN
WHERE id = c_id;
END delCustomer;
PROCEDURE listCustomer IS
CURSOR c_customers is
BEGIN
name_list.extend;
name_list(counter) := n.name;
END LOOP;
END listCustomer;
END c_package;
The above example makes use of the nested table. We will discuss the concept of
nested table in the next chapter.
When the above code is executed at the SQL prompt, it produces the following
result −
The following program uses the methods declared and defined in the
package c_package.
DECLARE
code customers.id%type:= 8;
BEGIN
c_package.listcustomer;
c_package.delcustomer(code);
c_package.listcustomer;
END;
When the above code is executed at the SQL prompt, it produces the following
result −
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Customer(7): Rajnish
Customer(8): Subham
Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal
Customer(7): Rajnish
A successfully executed SQL statement and a committed transaction are not same.
Even if an SQL statement is executed successfully, unless the transaction
containing the statement is committed, it can be rolled back and all changes made
by the statement(s) can be undone.
A transaction has a beginning and an end. A transaction starts when one of the
following events take place −
Committing a Transaction
COMMIT;
For example,
COMMIT;
Changes made to the database without COMMIT could be undone using the
ROLLBACK command.
ROLLBACK;
Savepoints
Savepoints are sort of markers that help in splitting a long transaction into smaller
units by setting some checkpoints. By setting savepoints within a long transaction,
you can roll back to a checkpoint if required. This is done by issuing
the SAVEPOINT command.
For example
SAVEPOINT sav1;
UPDATE CUSTOMERS
ROLLBACK TO sav1;
UPDATE CUSTOMERS
WHERE ID = 7;
UPDATE CUSTOMERS
WHERE ID = 8;
COMMIT;
ROLLBACK TO sav1 − This statement rolls back all the changes up to the point,
where you had marked savepoint sav1.
After that, the new changes that you make will start.
You can turn-off the auto commit mode using the following command −
Transaction
Example: Suppose an employee of bank transfers Rs 800 from X's account to Y's
account. This small transaction contains several low-level tasks:
X's Account
1. Open_Account(X)
2. Old_Balance = X.balance
4. X.balance = New_Balance
5. Close_Account(X)
Y's Account
1. Open_Account(Y)
2. Old_Balance = Y.balance
4. Y.balance = New_Balance
5. Close_Account(Y)
Operations of Transaction:
Read(X): Read operation is used to read the value of X from the database and
stores it in a buffer in main memory.
Write(X): Write operation is used to write the value back to the database from the
buffer.
1. 1. R(X);
2. 2. X = X - 500;
3. 3. W(X);
o The first operation reads X's value from database and stores it in a buffer.
o The second operation will decrease the value of X by 500. So buffer will
contain 3500.
o The third operation will write the buffer's value to the database. So X's final
value will be 3500.
But it may be possible that because of the failure of hardware, software or power,
etc. that transaction may fail before finished all the operations in the set.
For example: If in the above transaction, the debit transaction fails after executing
operation 2 then X's value will remain 4000 in the database which is not acceptable
by the bank.
Transaction property
The transaction has the four properties. These are used to maintain consistency in a
database, before and after the transaction.
Property of Transaction
1. Atomicity
2. Consistency
3. Isolation
4. Durability
Atomicity
o It states that all operations of the transaction take place at once if not, the
transaction is aborted.
Abort: If a transaction aborts then all the changes made are not visible.
Commit: If a transaction commits then all the changes made are visible.
T1 T2
Read(A) Read(B)
A:= A-100 Y:= Y+100
Write(A) Write(B)
Consistency
o The execution of a transaction will leave a database in either its prior stable
state or a new stable state.
o The transaction is used to transform the database from one consistent state to
another consistent state.
For example: The total amount must be maintained before or after the transaction.
Isolation
o It shows that the data which is used at the time of execution of a transaction
cannot be used by the second transaction until the first one is completed.
o In isolation, if the transaction T1 is being executed and using the data item
X, then that data item can't be accessed by any other transaction T2 until the
transaction T1 ends.
Durability
States of Transaction
Active state
o The active state is the first state of every transaction. In this state, the
transaction is being executed.
o For example: Insertion or deletion or updating a record is done here. But all
the records are still not saved to the database.
Partially committed
o In the partially committed state, a transaction executes its final operation, but
the data is still not saved to the database.
o In the total mark calculation example, a final display of the total marks step
is executed in this state.
Committed
Failed state
o If any of the checks made by the database recovery system fails, then the
transaction is said to be in the failed state.
o In the example of total mark calculation, if the database is not able to fire a
query to fetch the marks, then the transaction will fail to execute.
Aborted
o If any of the checks fail and the transaction has reached a failed state then
the database recovery system will make sure that the database is in its
previous consistent state. If not then it will abort or roll back the transaction
to bring the database into a consistent state.
o If the transaction fails in the middle of the transaction then before executing
the transaction, all the executed transactions are rolled back to its consistent
state.
o After aborting the transaction, the database recovery module will select one
of the two operations:
But before knowing about concurrency control, we should know about concurrent
execution.
o In a multi-user system, multiple users can access and use the same database
at one time, which is known as the concurrent execution of the database. It
means that the same database is executed simultaneously on a multi-user
system by different users.
The problem occurs when two different database transactions perform the
read/write operations on the same database items in an interleaved manner (i.e.,
concurrent execution) that makes the values of the items incorrect hence making
the database inconsistent.
For example:
Consider the below diagram where two transactions TX and TY, are
performed on the same account A where the balance of account A is $300.
o At time t1, transaction TX reads the value of account A, i.e., $300 (only
read).
o At time t2, transaction TX deducts $50 from account A that becomes $250
(only deducted and not updated/write).
o Alternately, at time t3, transaction TY reads the value of account A that will
be $300 only because TX didn't update the value yet.
o At time t4, transaction TY adds $100 to account A that becomes $400 (only
added but not updated/write).
o At time t6, transaction TX writes the value of account A that will be updated
as $250 only, as TY didn't update the value yet.
The dirty read problem occurs when one transaction updates an item of the
database, and somehow the transaction fails, and before the data gets rollback, the
updated database item is accessed by another transaction. There comes the Read-
Write Conflict between both transactions.
For example:
o At time t3, transaction TX writes the updated value in account A, i.e., $350.
o Then at time t4, transaction TY reads account A that will be read as $350.
o Then at time t5, transaction TX rollbacks due to server problem, and the
value changes back to $300 (as initially).
o But the value for account A remains $350 for transaction TY as committed,
which is the dirty read and therefore known as the Dirty Read Problem.
For example:
o At time t1, transaction TX reads the value from account A, i.e., $300.
o At time t2, transaction TY reads the value from account A, i.e., $300.
o After that, at time t5, transaction TX reads the available value of account A,
and that will be read as $400.
o It means that within the same transaction TX, it reads two different values of
account A, i.e., $ 300 initially, and after updation made by transaction TY, it
reads $400. It is an unrepeatable read and is therefore known as the
Unrepeatable read problem.
Thus, in order to maintain consistency in the database and avoid such problems
that take place in concurrent execution, management is needed, and that is where
the concept of Concurrency Control comes into role.
Concurrency Control
Concurrency Control is the working concept that is required for controlling and
managing the concurrent execution of database operations and thus avoiding the
inconsistencies in the database. Thus, for maintaining the concurrency of the
database, we have the concurrency control protocols.
We will understand and discuss each protocol one by one in our next section
Schedule
1. Serial Schedule
For example: Suppose there are two transactions T1 and T2 which have some
operations. If it has no interleaving of operations, then there are the following two
possible outcomes:
1. Execute all the operations of T1 which was followed by all the operations of
T2.
2. Execute all the operations of T1 which was followed by all the operations of
T2.
o In the given (a) figure, Schedule A shows the serial schedule where T1
followed by T2.
o In the given (b) figure, Schedule B shows the serial schedule where T2
followed by T1.
2. Non-serial Schedule
o It contains many possible orders in which the system can execute the
individual operations of the transactions.
o In the given figure (c) and (d), Schedule C and Schedule D are the non-serial
schedules. It has interleaving of operations.
3. Serializable schedule
Here,
Testing of Serializability
For example:
Explanation:
The precedence graph for schedule S1 contains a cycle that's why Schedule S1 is
non-serializable.
Explanation:
The precedence graph for schedule S2 contains no cycle that's why ScheduleS2 is
serializable.
Conflicting Operations
Example:
Conflict Equivalent
Example:
T1 T2
Read(A)
Write(A)
Read(B)
Write(B)
Read(A)
Write(A)
Read(B)
Write(B)
View Serializability
o The view serializable which does not conflict serializable contains blind
writes.
View Equivalent
Two schedules S1 and S2 are said to be view equivalent if they satisfy the
following conditions:
1. Initial Read
An initial read of both schedules must be the same. Suppose two schedule S1 and
S2. In schedule S1, if a transaction T1 is reading the data item A, then in S2,
transaction T1 should also read A.
Above two schedules are view equivalent because Initial read operation in S1 is
done by T1 and in S2 it is also done by T1.
2. Updated Read
Above two schedules are not view equal because, in S1, T3 is reading A updated
by T2 and in S2, T3 is reading A updated by T1.
3. Final Write
A final write must be the same between both the schedules. In schedule S1, if a
transaction T1 updates A at last then in S2, final writes operations should also be
done by T1.
Above two schedules is view equal because Final write operation in S1 is done by
T3 and in S2, the final write operation is also done by T3.
Example:
Schedule S
1. = 3! = 6
2. S1 = <T1 T2 T3>
3. S2 = <T1 T3 T2>
4. S3 = <T2 T3 T1>
5. S4 = <T2 T1 T3>
6. S5 = <T3 T1 T2>
7. S6 = <T3 T2 T1>
Schedule S1
In both schedules S and S1, there is no read except the initial read that's why we
don't need to check that condition.
The initial read operation in S is done by T1 and in S1, it is also done by T1.
The final write operation in S is done by T3 and in S1, it is also done by T3. So, S
and S1 are view Equivalent.
The first schedule S1 satisfies all three conditions, so we don't need to check
another schedule.
1. T1 → T2 → T3
But before knowing about concurrency control, we should know about concurrent
execution.
o In a multi-user system, multiple users can access and use the same database
at one time, which is known as the concurrent execution of the database. It
means that the same database is executed simultaneously on a multi-user
system by different users.
The problem occurs when two different database transactions perform the
read/write operations on the same database items in an interleaved manner (i.e.,
concurrent execution) that makes the values of the items incorrect hence making
the database inconsistent.
For example:
Consider the below diagram where two transactions TX and TY, are
performed on the same account A where the balance of account A is $300.
o At time t1, transaction TX reads the value of account A, i.e., $300 (only
read).
o At time t2, transaction TX deducts $50 from account A that becomes $250
(only deducted and not updated/write).
o Alternately, at time t3, transaction TY reads the value of account A that will
be $300 only because TX didn't update the value yet.
o At time t4, transaction TY adds $100 to account A that becomes $400 (only
added but not updated/write).
o At time t6, transaction TX writes the value of account A that will be updated
as $250 only, as TY didn't update the value yet.
The dirty read problem occurs when one transaction updates an item of the
database, and somehow the transaction fails, and before the data gets rollback, the
updated database item is accessed by another transaction. There comes the Read-
Write Conflict between both transactions.
For example:
o At time t3, transaction TX writes the updated value in account A, i.e., $350.
o Then at time t4, transaction TY reads account A that will be read as $350.
o Then at time t5, transaction TX rollbacks due to server problem, and the
value changes back to $300 (as initially).
o But the value for account A remains $350 for transaction TY as committed,
which is the dirty read and therefore known as the Dirty Read Problem.
For example:
o At time t1, transaction TX reads the value from account A, i.e., $300.
o At time t2, transaction TY reads the value from account A, i.e., $300.
o After that, at time t5, transaction TX reads the available value of account A,
and that will be read as $400.
o It means that within the same transaction TX, it reads two different values of
account A, i.e., $ 300 initially, and after updation made by transaction TY, it
reads $400. It is an unrepeatable read and is therefore known as the
Unrepeatable read problem.
Thus, in order to maintain consistency in the database and avoid such problems
that take place in concurrent execution, management is needed, and that is where
the concept of Concurrency Control comes into role.
Concurrency Control
Concurrency Control is the working concept that is required for controlling and
managing the concurrent execution of database operations and thus avoiding the
inconsistencies in the database. Thus, for maintaining the concurrency of the
database, we have the concurrency control protocols.
We will understand and discuss each protocol one by one in our next sections.
Lock-Based Protocol
In this type of protocol, any transaction cannot read or write data until it acquires
an appropriate lock on it. There are two types of lock:
1. Shared lock:
o It is also known as a Read-only lock. In a shared lock, the data item can only
read by the transaction.
o It can be shared between the transactions because when the transaction holds
a lock, then it can't update the data on the data item.
2. Exclusive lock:
o In the exclusive lock, the data item can be both reads as well as written by
the transaction.
o This lock is exclusive, and in this lock, multiple transactions do not modify
the same data simultaneously.
It is the simplest way of locking the data while transaction. Simplistic lock-based
protocols allow all the transactions to get the lock on the data before insert or
delete or update on it. It will unlock the data item after completing the transaction.
o Pre-claiming Lock Protocols evaluate the transaction to list all the data items
on which they need locks.
o If all the locks are granted then this protocol allows the transaction to begin.
When the transaction is completed then it releases all the lock.
o If all the locks are not granted then this protocol allows the transaction to
rolls back and waits until all the locks are granted.
o In the first part, when the execution of the transaction starts, it seeks
permission for the lock it requires.
o In the second part, the transaction acquires all the locks. The third phase is
started as soon as the transaction releases its first lock.
o In the third phase, the transaction cannot demand any new locks. It only
releases the acquired locks.
Growing phase: In the growing phase, a new lock on the data item may be
acquired by the transaction, but none can be released.
Shrinking phase: In the shrinking phase, existing lock held by the transaction may
be released, but no new locks can be acquired.
In the below example, if lock conversion is allowed then the following phase can
happen:
Example:
The following way shows how unlocking and locking work with 2-PL.
Transaction T1:
o Lock point: at 3
Transaction T2:
o Lock point: at 6
o The first phase of Strict-2PL is similar to 2PL. In the first phase, after
acquiring all the locks, the transaction continues to execute normally.
o The only difference between 2PL and strict 2PL is that Strict-2PL does not
release a lock after using it.
o Strict-2PL waits until the whole transaction to commit, and then it releases
all the locks at a time.
o The priority of the older transaction is higher that's why it executes first. To
determine the timestamp of the transaction, this protocol uses system time or
logical counter.
o Let's assume there are two transactions T1 and T2. Suppose the transaction
T1 has entered the system at 007 times and transaction T2 has entered the
system at 009 times. T1 has the higher priority, so it executes first as it is
entered the system first.
o The timestamp ordering protocol also maintains the timestamp of last 'read'
and 'write' operation on a data.
o If TS(Ti) < W_TS(X) then the operation is rejected and Ti is rolled back
otherwise the operation is executed.
Where,
o But the schedule may not be recoverable and may not even be cascade- free.
Deadlock in DBMS
For example: In the student table, transaction T1 holds a lock on some rows and
needs to update some rows in the grade table. Simultaneously, transaction T2 holds
locks on some rows in the grade table and needs to update the rows in the Student
table held by Transaction T1.
Now, the main problem arises. Now Transaction T1 is waiting for T2 to release its
lock and similarly, transaction T2 is waiting for T1 to release its lock. All activities
come to a halt state and remain at a standstill. It will remain in a standstill until the
DBMS detects the deadlock and aborts one of the transactions.
Deadlock Avoidance
Deadlock Detection
o This is the suitable method for deadlock detection. In this method, a graph is
created based on the transaction and their lock. If the created graph has a
cycle or closed loop, then there is a deadlock.
o The wait for the graph is maintained by the system for every transaction
which is waiting for some data held by the others. The system keeps
checking the graph if there is any cycle in the graph.
The wait for a graph for the above scenario is shown below:
Deadlock Prevention
Wait-Die scheme
In this scheme, if a transaction requests for a resource which is already held with a
conflicting lock by another transaction then the DBMS simply checks the
timestamp of both transactions. It allows the older transaction to wait until the
resource is available for execution.
Let's assume there are two transactions Ti and Tj and let TS(T) is a timestamp of
any transaction T. If T2 holds a lock by some other transaction and T1 is
requesting for resources held by T2 then the following actions are performed by
DBMS:
1. Check if TS(Ti) < TS(Tj) - If Ti is the older transaction and Tj has held
some resource, then Ti is allowed to wait until the data-item is available for
execution. That means if the older transaction is waiting for a resource
which is locked by the younger transaction, then the older transaction is
allowed to wait for resource until it is available.
2. Check if TS(Ti) < TS(Tj) - If Ti is older transaction and has held some
resource and if Tj is waiting for it, then Tj is killed and restarted later with
the random delay but with the same timestamp.
o In wound wait scheme, if the older transaction requests for a resource which
is held by the younger transaction, then older transaction forces younger one
to kill the transaction and release the resource. After the minute delay, the
younger transaction is restarted but with the same timestamp.
When a system crashes, it may have several transactions being executed and
various files opened for them to modify the data items. Transactions are made of
various operations, which are atomic in nature. But according to ACID properties
of DBMS, atomicity of transactions as a whole must be maintained, that is, either
all the operations are executed or none.
It should check the states of all the transactions, which were being executed.
There are two types of techniques, which can help a DBMS in recovering as well
as maintaining the atomicity of a transaction −
Maintaining the logs of each transaction, and writing them onto some stable
storage before actually modifying the database.
Log-based Recovery
When a transaction enters the system and starts execution, it writes a log
about it.
<Tn, Start>
<Tn, commit>
When more than one transaction are being executed in parallel, the logs are
interleaved. At the time of recovery, it would become hard for the recovery system
to backtrack all logs, and then start recovering. To ease this situation, most modern
DBMS use the concept of 'checkpoints'.
Checkpoint
Keeping and maintaining logs in real time and in real environment may fill out all
the memory space available in the system. As time passes, the log file may grow
too big to be handled at all. Checkpoint is a mechanism where all the previous logs
are removed from the system and stored permanently in a storage disk. Checkpoint
declares a point before which the DBMS was in consistent state, and all the
transactions were committed.
Recovery
When a system with concurrent transactions crashes and recovers, it behaves in the
following manner −
The recovery system reads the logs backwards from the end to the last
checkpoint.
If the recovery system sees a log with <Tn, Start> and <Tn, Commit> or just
<Tn, Commit>, it puts the transaction in the redo-list.
If the recovery system sees a log with <Tn, Start> but no commit or abort log
found, it puts the transaction in undo-list.
All the transactions in the undo-list are then undone and their logs are removed. All
the transactions in the redo-list and their previous logs are removed and then
redone before saving their logs.
o Whenever more than one transaction is being executed, then the interleaved
of logs occur. During recovery, it would become difficult for the recovery
system to backtrack all logs and then start recovering.
References:
o https://www.javatpoint.com/
o https://www.tutorialspoint.com/