Beruflich Dokumente
Kultur Dokumente
What is a transaction?
A transaction is a series of one or more SQL statements that are logically related or a series of
operations performed on an Oracle table.
This logical unit is treated as an entity by Oracle. All changes to the data table are viewed as a
two-step process. Step 1: Make the changes requested, and Step 2: This must be followed by
the COMMIT statement. A ROLLBACK statement given at the SQL prompt can be used to
undo a part of or the entire transaction.
A transaction begins with the first executable SQL statement after a COMMIT, ROLLBACK,
or connection made to the Oracle engine.
A transaction is a group of events that occur between any of the following events:
1. Connecting to Oracle
2. Disconnecting from Oracle
3. Committing changes to the database table
4. Rollback
Closing transaction: a transaction is closed by either a commit or a rollback statement.
COMMIT statement: This statement ends the current transaction and changes are made
permanent.
Syntax:
COMMIT
ROLLBACK statement: This statement does exactly the opposite of the COMMIT statement.
It ends the transaction but undoes any changes made during the transaction. All transactional
locks are released from the tables.
Syntax:
ROLLBACK [TO [SAVEPOINT] <savepointname>];
SAVEPOINT is optional and is used to roll back a transaction partially.
savepointname is a savepoint ceated during the current transaction.
2.
mukeshtekwani@hotmail.com
active SAVEPOINT is one that is specified since the last COMMIT or ROLLBACK.
Syntax:
SAVEPOINT <savepointname>;
A ROLLBACK command can be given even without giving the SAVEPOINT clause.
If the ROLLBACK command is given without the SAVEPOINT option, the following take
place:
1. It ends the current transaction.
2. Undoes all the changes in the current transaction
3. Erases all the savepoints in that transaction
4. Releases the transactional locks.
If the ROLLBACK command is given with the TO SAVEPOINT option, the following take
place:
1. A predetermined portion of the transaction is rolled back
2. Retains the save point rolled to but loses those created after the savepoint.
3. Releases all transactional locks
3
Write a PL/SQL block of code that first withdraws an amount of Rs 1000. Then deposits
an amount of Rs 1,40,000. Update the current balance. Then check to see that the current
balance of all the accounts in the bank does not exceed 2,00,000. If the balance exceeds
2,00,000, then undo the deposit just made.
DECLARE
mBAL NUMBER(8, 2);
BEGIN
/* insert a record into TRANSMSTR for withdrawls */
INSERT INTO TRANSMSTR (TRANSNO, ACCTNO, DT, TYPE, TDETAILS,
DR_CR, AMT, BALANCE);
VALUES (T100, SB10, 07-OCT-2010, W, Mobile Bill, W, 1000, 30000);
/*Update the current balance of this account no, in the ACCTMSTR table */
UPDATE ACCTMSTR
SET CURBAL = CURBAL 1000
WHERE ACCTNO = SB10;
/* Define a savepoint */
SAVEPOINT no_update;
/*insert a record into transactionmaster for deposits */
INSERT INTO TRANSMSTR (TRANSNO, ACCTNO, DT, TYPE, TDETAILS,
DR_CR, AMT, BALANCE);
VALUES (T101, SB10, 07-OCT-2010, C, Deposit, D, 14000, 171000);
/* update the current balance of account no SB10 in the ACCTMSTR table */
UPDATE ACCTMSTR SET CURBAL = CURBAL + 140000 WHERE ACCTNO =
SB10;
/*store the total current balance from the ACCTMSTR table into a variable */
SELECT SUM(CURBAL) INTO mBAL from acctmstr;
mukeshtekwani@hotmail.com
mukeshtekwani@hotmail.com
Attributes of Cursors:
1. When the Oracle engine creates an implicit or explicit cursor, it also creates cursor control
variables.
2. These variables are used to control the execution of the cursor.
3. There are four system variables that keep track of the current status of the cursor. These
cursor variables can be used in a PL/SQL block.
4. The four attributes of all cursors are:
Attribute Name
Description
%ISOPEN
Returns TRUE if the cursor is open, FALSE otherwise
%FOUND
Returns TRUE if record was fetched successfully, FALSE
otherwise
%NOTFOUND
Returns TRUE if record was not fetched successfully, FALSE
otherwise
%ROWCOUNT
Returns number of records processed from the cursor
%FOUND
%NOTFOUND
%ROWCOUNT
Description
The Oracle engine automatically opens and closes the SQL
cursor after executing the INSERT, DELETE, SELECT, or
UPDATE operations. Thus, the SQL%ISOPEN attribute of an
implicit cursor cannot be referenced outside of its SQL
statement. Hence, SQL%ISOPEN always evaluates to FALSE.
This evaluates to TRUE if an INSERT, UPDATE, or DELETE
affected one or more rows, or a single-row SELECT returned
one or more rows. Otherwise it evaluates to FALSE. This
attribute can be accessed as follows: SQL%FOUND.
This is the logical opposite of the %FOUND attribute. It
evaluates to TRUE if the INSERT, UPDATE or DELETE did
not any rows. Otherwise it evaluates to FALSE.
Returns number of records affected by an INSERT, UPDATE,
or DELETE statements. Syntax is : SQL%ROWCOUNT
mukeshtekwani@hotmail.com
Example 1: A bank manager has decided to transfer employees across branches. Write
PL/SQL code to accept an employee number and the branch number followed by updating the
branch number of that employee to which he belongs. Display an appropriate message using
SQL%NOTFOUND based on the non-existence of the record in the EMP_MSTR table.
BEGIN
UPDATE EMP_MSTR SET BRANCH_NO = &BRANCH_NO
WHERE EMPNO = &EMPNO
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE (Employee successfully transferred);
END IF;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE (Employee number does not exist);
END IF;
END;
Example 2:
The bank manager of Bandra branch decides to activate all those accounts which were
previously marked as inactive for performing no transactions in the last 365 days. Write a
PL/SQL block to update the status of accounts. Display an appropriate message based on the
number of rows affected by the update fired.
DECLARE
Rows_Affected char(4);
BEGIN
UPDATE ACCT_MSTR SET STATUS = A WHERE STATUS = S AND
BRANCH_NO IN (SELECT BRANCH_NO FROM BRANCH_MSTR WHERE
NAME = Bandra);
Rows_Affected := TO_CHAR(SQL%ROWCOUNT);
IF SQL%ROWCOUNT > 0 THEN
DBMS_OUTPUT.PUT_LINE(Rows_Affected || accounts activated
successfully);
ELSE
DBMS_OUTPUT.PUT_LINE(Currently there are no inactive accounts in the
Bandra branch);
END IF;
END;
Example 3: In this code, we use implicit cursors to display a message stating whether or not
employees salaries were updated.
DECLARE
var_rows number(5);
BEGIN
UPDATE employee
SET salary = salary + 1000;
IF SQL%NOTFOUND THEN
dbms_output.put_line('None of the salaries where updated');
mukeshtekwani@hotmail.com
mukeshtekwani@hotmail.com
DECLARE
variables;
create a cursor;
BEGIN
OPEN cursor;
FETCH cursor;
process the records;
CLOSE cursor;
END;
Example 1: The bank manager has decided to mark all those accounts as inactive (I) on which
there are no transactions performed in the last 365 days. Whenever any such update takes
place, a record for the same is maintained in the INACTIVE_MSTR table which contains the
account number, the opening date and the type of account. Write a PL/SQL block to implement
this.
We first create the INACTIVE_MSTR table as follows:
CREATE TABLE INACTIVE_MSTR
(ACCTNO VARCHAR2(10),
OPENDT DATE,
TYPE VARCHAR2(2));
Now we write the PL/SQL code block:
DECLARE
CURSOR Crsr_NoTrans IS
SELECT ACCTNO, STATUS, OPENDT, TYPE FROM ACCT_MSTR
WHERE ACCTNO IN (SELECT ACCTNO FROM TRANS_MSTR
GROUP BY ACCTNO HAVING MAX(SYSDATE OPENDT) > 365;
/* declare memory variables to hold data fetched from the cursor */
str_ACCTNO ACCTMSTR.ACCTNO%TYPE;
str_STATUS ACCTMSTR.STATUS%TYPE;
dt_OPENDT ACCTMSTR.OPENDT%TYPE;
str_TYPE
ACCTMSTR.TYPE%TYPE;
BEGIN
OPEN Crsr_NoTrans;
/* if the cursor is open, continue with the data processing else display an appropriate
error message */
IF Crsr_NoTrans%ISOPEN THEN
LOOP
FETCH Crsr_NoTrans INTO str_ACCTNO, str_STATUS, dt_OPENDT,
str_TYPE;
EXIT WHEN Crsr_NoTrans%NOTFOUND;
IF Crsr_NoTrans%FOUND THEN
/*update status to I and insert each record into the INACTIVE_MSTR
table */
UPDATE ACCTMSTR SET STATUS = I WHERE ACCTNO =
mukeshtekwani@hotmail.com
str_ACCTNO;
INSERT INTO INACTIVE_MSTR VALUE (str_ACCTNO,
dt_opendt, str_TYPE);
END IF;
END LOOP;
/*make the changes permanent */
COMMIT
ELSE
Dbms_output.put_line (Error: Unable to open cursor);
END IF;
CLOSE Crsr_NoTrans;
END;
In the above example, the %TYPE means that the data type of these variables will be as that
from the table.
Since the query may return more than one row, a loop is created which does the following:
(i)
Fetch the data retrieved by the cursor into the variable.
(ii)
Check if any data is retrieved
a. Update the status field of the AACT_MSTR table to indicate that the account is
inactive.
b. Insert a record in the INACTIVE_MSTR table
(iii) Repeat the above steps until the data retrieval process is completed.
(iv)
Finally, the COMMIT statement is executed to make the changes permanent.
Example 2: Write a PL/SQL block that will display the customer name, the fixed deposit
number and the fixed deposit amount of the first 5 customers holding the highest amount in
fixed deposits.
DECLARE
CURSOR Crsr_HiFD IS
SELECT Fname || || LNAME, FDNO, AMT
FROM CUST_MSTR C, ACCT_FD_CUST_DETAILS A, FD_DETAILS F
WHERE C.CUSTNO = A.CUSTNO AND A.FDNO = F.FDSRNO
ORDER BY AMT Desc;
str_NAME VARCHAR2(40);
str_FDNO FD_DETAILS.FDNO%type;
num_AMT FD_DETAILS.AMT%type;
BEGIN
OPEN Crsr_HiFD;
dbms_output.put_line (Name
FD No.
Amount);
dbms_output.put_line (-------------------------------------------------------------);
LOOP
FETCH Crsr_HiFD INTO str_NAME, str_FDNO, num_AMT;
EXIT WHEN (Crscr_HiFD%ROWCOUNT-1) = 5 OR
Crscr_HiFD%NOTFOUND;
dbms_output.put_line (str_NAME || || str_FDNO || || num_AMT);
Prof. Mukesh N Tekwani
mukeshtekwani@hotmail.com
END LOOP;
END;
To retrieve the records, both the tables have to be linked on the basis of common columns
using join as follows:
mukeshtekwani@hotmail.com
10
Example 2: The bank manager has decided to marks all those accounts as inactive (I) on
which there are no transactions performed in the last 365 days. Whenever any such update
takes place, a record for the same is maintained in the INACTIVE_MSTR table. This table
consists of the fields account number, opening date and type of account. Write PL/SQL code
block to do the same.
First we create the INACTIVE_MSTR table.
CREATE TABLE IANCTIVE_MSTR (
ACCTNO VARCHAR2(10),
OPENDT DATE,
ACCTYPE VARCHAR2(2));
Now we write the PL/SQL code block:
DECLARE
CURSOR Crsr_NoTrans IS
SELECT ACCTNO, STATUS, OPENDT, ACCTYPE FROM ACCTMSTR
WHERE ACCTNO IN (SELECT ACCTNO FROM TRANSMSTR
GROUP BY ACCTNO
HAVING MAX(SYSDATE OPENDT) > 365;
BEGIN
/* we use the cursor FOR loop */
FOR NoTransRec IN Crsr_NoTrans
/* update the inactive status and insert each record into the INACTIVE_MSTR table */
UPDATE ACCT_MSTR SET STATUS = I
WHERE ACCTNO= NoTransRec.ACCTNO;
INSERT INTO INACTIVE_MSTR
VALUES(NoTransRec.ACCTNO, NoTransRec.OPENDATE, NoTransRec.ACCTYPE);
END LOOP;
COMMIT;
END;
Since a FOR loop is used in this example, we did not declare any variables. The cursor closes
automatically when all the records have been processed. This is because there are no more
records left to load into NoTransRec. Finally, the COMMIT statement is fired to make the
changes permanent.
9
mukeshtekwani@hotmail.com
local blocks.
Most commercial applications will require that the query which defines the cursor, be general
in nature and the data that is retrieved from the table be allowed to change according to the
users need. Oracle permits the use of parameterized cursor. The contents of the parameterized
cursor will change depending upon the value passed to its parameter.
Since the cursor accepts user0-defined values into its parameters, thus changing the result set
extracted from the table, it is called as a parameterized cursor.
Declaring a parameterized cursor:
CURSOR cursorname (varname datatype) IS <SELECT statement>
Opening a parameterized cursor and passing values to it:
OPEN cursorname (vale/variable/expression)
The scope of the cursor parameter is confined to that cursor. You cannot refer to the cursor
parameter outside of the SELECT statement associated with the cursor.
Example 1:
Write a PL/SQL code block that will merge the data available in the newly created table
NEW_BRANCHES with the data available in the table BRANCH_MASTER. If the data in the
first table already exists in the second table, then that data should be skipped.
CREATE TABLE NEW_BRANCHES(
BRANCHNO VARCHAR2(10),
NAME VARCHAR2(30));
INSERT INTO NEW_BRANCHES (BRANCHNO, NAME) VALUES (B4, MAHIM);
INSERT INTO NEW_BRANCHES (BRANCHNO, NAME) VALUES (B5, MATUNGA);
INSERT INTO NEW_BRANCHES (BRANCHNO, NAME) VALUES (B6, DADAR);
INSERT INTO NEW_BRANCHES (BRANCHNO, NAME) VALUES (B7, KHAR);
Now WE WRITE THE PL/SQL CODE BLOCK:
DECLARE
/* This cursor retrieves all records of NEW_BRANCHES table */
CURSOR Crsr_Newbranches (str_BRANCHNAME VARCHAR2) IS
SELECT * FROM NEW_BRANCHES;
/* this cursor accepts the value of NAME from the current row of the cursor Crsr_Newbranches */
CURSOR Crsr_Branchchk (str_BRANCHNAME varchar2) IS
SELECT BRANCHNO FROM BRANCHMSTR
WHERE NAME = str_BRANCHNAME;
/* we create variables that hold the data from the cursor Crsr_Newbranches */
str_BRANCHNO BRANCH_MSTR.BRANCHNO.%TYPE;
str_BRANCHNNAME BRANCH_MSTR.NAME.%TYPE;
/* we create a variable that holds data from the cursor Crsr_Branchchk */
temp VARCHAR2(10);
mukeshtekwani@hotmail.com
11
12
BEGIN
/* open the Crsr_Newbranches cursor */
OPEN Crsr_Newbranches;
LOOP
/* fetch the records from the Crsr_Newbranches cursor */
FETCH Crsr_Newbranches INTO str_BRANCHNO, str_BRANCHNAME;
EXIT WHEN Crsr_Newbranches%NOTFOUND;
/* open the Crsr_Branchchk cursor. Note that the value of variable passed to the
CrsrBranchchk cursor is set to the value of NAME in the current row of the cursor
Crsr_Newbranches */
OPEN Crsr_Branchchk(str_BRANCHNAME);
FETCH Crsr_Branchchk INTO temp;
IF Crsr_BRANCHCHK%FOUND THEN
dbms_output.put_line (Branch || str_BRANCHNAME || exists);
ELSE
dbms_output.put_line (Branch || str_BRANCHNAME || does not exist. Inserting
new branch in database);
INSERT INTO BRANCH_MSTR VALUES (str_BRANCHNO,
str_BRANCHNAME);
END IF;
CLOSE Crsr_BRANCHCHK;
END LOOP;
CLOSE Crsr_Newbranches;
COMMIT;
END;
mukeshtekwani@hotmail.com