1600 PMP mock questions 1400 CAPM mock questions 800 SCJP 6 mock questions 600 OCAJP 7 mock questions 590 OCPJP 7 mock questions 556 SCWCD 5 mock questions 500 OCEJWCD 6 mock questions pdfDownload (java,struts, hibernet etc)

ORACLE Tutorials

SQL Cursor in Oracle Detailed

SQL Cursor
A SQL cursor is a private Oracle SQL working area. There are two types of SQL cursor: implicit or explicit cursor. The implicit cursor is used by Oracle server to test and parse the SQL statements and the explicit cursors are declared by the programmers.
Using the implicit cursor, we can test the outcome of SQL statements in PL/SQL. For example,
?    SQL%ROWCOUNT, return the number of rows affected;
?    SQL%FOUND, a BOOLEAN attribute indicating whether the recent SQL statement matches to any row;
?    SQL%NOTFOUND, a BOOLEAN attribute indicating whether the recent SQL statement does not match to any row;
?    SQL%ISOPEN, a BOOLEAN attribute and always evaluated as FALSE immediately after the SQL statement is executed.
To write the explicit cursor, please refer to the following example. Note that a cursor definition can array a number of arguments.
For example,
CURSOR csr_ac (p_name VARCHAR2) IS
SELECT empno, name, sal
FROM employee
WHERE name LIKE '%p_name%';
FOR rec_ac IN csr_ac ('LE')
DBMS_OUTPUT.PUT_LINE(rec_ac.empno || ' ' ||rec_ac.name || ' '||v_sal);
CLOSE csr_ac;
Another way of writing the above code, is to use the basic loop and the SQL%NOTFOUND cursor, as shown in the following.
2 CURSOR csr_ac (p_name VARCHAR2) IS
3 SELECT empno, ename, sal
4 FROM emp
6 WHERE ename LIKE '%SMITH%';
8 v_a emp.empno%TYPE;
9 v_b emp.ename%TYPE;
10 v_c emp.sal%TYPE;
13 OPEN csr_ac('');
15 FETCH csr_ac INTO v_a, v_b, v_c;
18 DBMS_OUTPUT.PUT_LINE(v_a || ' ' || v_b || ' '||v_c);
21 CLOSE csr_ac;
22 END;
25 /
7369 SMITH 800

Cursors in PL/SQL
Every SQL statement executed by the RDBMS has a private SQL area that contains information about the SQL statement and the set of data returned. In PL/SQL, a cursor is a name assigned to a specific private SQL area for a specific SQL statement. There can be either static cursors, whose SQL statement is determined at compile time, or dynamic cursors, whose SQL statement is determined at runtime. Static cursors are covered in greater detail in this section. Dynamic cursors in PL/SQL are implemented via the built-in package DBMS_SQL. See the book Oracle Built-in Packages and the corresponding Oracle PL/SQL Built-ins Pocket Reference, both from O'Reilly & Associates, for full coverage on DBMS_SQL and the other built-in packages.
Explicit Cursors
Explicit cursors are SELECT statements that are DECLAREd explicitly in the declaration section of the current block or in a package specification. Use OPEN, FETCH, and CLOSE in the execution or exception sections of your programs.
1.1 Declaring explicit cursors
To use an explicit cursor, you must first declare it in the declaration section of a block or package. There are three types of explicit cursor declarations:
?    A cursor without parameters, such as:
CURSOR company_cur
SELECT company_id FROM company;
?    A cursor that accepts arguments through a parameter list:
CURSOR company_cur (id_in IN NUMBER) IS
SELECT name FROM company
WHERE company_id = id_in;
?    A cursor header that contains a RETURN clause in place of the SELECT statement:
CURSOR company_cur (id_in IN NUMBER)
SELECT * FROM company;
1.2 Opening explicit cursors
To open a cursor, use the following syntax:
OPEN cursor_name [(argument [,argument ...])];
where cursor_name is the name of the cursor as declared in the declaration section. The arguments are required if the definition of the cursor contains a parameter list.
You must open an explicit cursor before you can fetch rows from that cursor. When the cursor is opened, the processing includes the PARSE, BIND, OPEN, and EXECUTE statements. This OPEN processing includes: determining an execution plan, associating host variables and cursor parameters with the placeholders in the SQL statement, determining the result set, and, finally, setting the current row pointer to the first row in the result set.
When using a cursor FOR loop, the OPEN is implicit in the FOR statement. If you try to open a cursor that is already open, PL/SQL will raise an "ORA-06511: PL/SQL: cursor already open" exception.
1.3 Fetching from explicit cursors
The FETCH statement places the contents of the current row into local variables. To retrieve all rows in a result set, each row needs to be fetched. The syntax for a FETCH statement is:
FETCH cursor_name INTO record_or_variable_list;
where cursor_name is the name of the cursor as declared and opened.
1.4 Closing explicit cursors
The syntax of the CLOSE statement is:
CLOSE cursor_name;
where cursor_name is the name of the cursor declared and opened.
After all rows have been fetched, a cursor needs to be closed. Closing a cursor releases the private SQL area used by the cursor, freeing the memory used by that cursor.
If you declare a cursor in a local anonymous, procedure, or function block, that cursor will automatically close when the block terminates. Package-based cursors must be closed explicitly, or they stay open for the duration of your session. Closing a cursor that is not open raises an INVALID CURSOR exception.
1.5 Explicit cursor attributes
There are four attributes associated with cursors: ISOPEN, FOUND, NOTFOUND, and ROWCOUNT. These attributes can be accessed with the % delimiter to obtain information about the state of the cursor. The syntax for a cursor attribute is:
where cursor_name is the name of the explicit cursor.
The behaviors of the explicit cursor attributes are described in the following table.
Attribute    Description
%ISOPEN    TRUE if cursor is open.
FALSE if cursor is not open.
%FOUND    INVALID_CURSOR is raised if cursor has not been OPENed.
NULL before the first fetch.
TRUE if record was fetched successfully.
FALSE if no row was returned.
INVALID_CURSOR if cursor has been CLOSEd.
%NOTFOUND    INVALID_CURSOR is raised if cursor has not been OPENed.
NULL before the first fetch.
FALSE if record was fetched successfully.
TRUE if no row was returned.
INVALID_CURSOR if cursor has been CLOSEd.
%ROWCOUNT    INVALID_CURSOR is raised if cursor has not been OPENed.
The number of rows fetched from the cursor.
INVALID_CURSOR if cursor has been CLOSEd.
Frequently a cursor attribute is checked as part of a WHILE loop that fetches rows from a cursor:
caller_rec caller_pkg.caller_cur%ROWTYPE;
OPEN caller_pkg.caller_cur;
FETCH caller_pkg.caller_cur into caller_rec;
EXIT WHEN caller_pkg.caller_cur%NOTFOUND
caller_pkg.caller_cur%ROWCOUNT > 10;

SET caller_id = caller_rec.caller_id
WHERE call_timestamp < SYSDATE;
CLOSE caller_pkg.caller_cur;

2 Implicit Cursors
Whenever a SQL statement is directly in the execution or exception section of a PL/SQL block, you are working with implicit cursors. These statements include INSERT, UPDATE, DELETE, and SELECT INTO statements. Unlike explicit cursors, implicit cursors do not need to be declared, OPENed, FETCHed, or CLOSEd.
SELECT statements handle the %FOUND and %NOTFOUND attributes differently from explicit cursors. When an implicit SELECT statement does not return any rows, PL/SQL immediately raises the NO_DATA_FOUND exception and control passes to the exception section. When an implicit SELECT returns more than one row, PL/SQL immediately raises the TOO_MANY_ROWS exception and control passes to the exception section.
Implicit cursor attributes are referenced via the SQL cursor. For example:
UPDATE activity SET last_accessed := SYSDATE
WHERE UID = user_id;

INSERT INTO activity_log (uid,last_accessed)
SQL Attributes    Description
%ISOPEN    Always FALSE since the cursor is opened implicitly and closed immediately after the statement is executed.
%FOUND    NULL before the statement.
TRUE if one or more rows were inserted, updated, or deleted or if only one row was selected.
FALSE if no row was selected, updated, inserted, or deleted.
%NOTFOUND    NULL before the statement.
TRUE if no row was selected, updated, inserted, or deleted.
FALSE if one or more rows were inserted, updated, or deleted.
%ROWCOUNT    The number of rows affected by the cursor.
%BULK_ROWCOUNT (Oracle8i)    A pseudo index-by table containing the numbers of rows affected by the statements executed in bulk bind operations. See the "Bulk Binds (Oracle8i)" section for more information on %BULK_ROWCOUNT.
Use the RETURNING clause in INSERT, UPDATE, and DELETE statements to obtain data modified by the associated DML statement. This clause allows you to avoid an additional SELECT statement to query the results of the DML statement. For example:
UPDATE activity SET last_accessed := SYSDATE
WHERE UID = user_id
RETURNING last_accessed, cost_center
INTO timestamp, chargeback_acct;

2.1 The SELECT FOR UPDATE clause
By default, the Oracle RDBMS locks rows as they are changed. To lock all rows in a result set, use the FOR UPDATE clause in your SELECT statement when you OPEN the cursor, instead of when you change the data. Using the FOR UPDATE clause does not require you to actually make changes to the data; it only locks the rows when opening the cursor. These locks are released on the next COMMIT or ROLLBACK. As always, these row locks do not affect other SELECT statements unless they, too, are FOR UPDATE. The FOR UPDATE clause is appended to the end of the SELECT statement and has the following syntax:
FROM ...
FOR UPDATE [OF column_reference] [NOWAIT];
where column_reference is a comma-delimited list of columns that appear in the SELECT clause. The NOWAIT keyword tells the RDBMS to not wait for other blocking locks to be released. The default is to wait forever.
In the following example, only columns from the inventory (pet) table are referenced FOR UPDATE, so no rows in the dog_breeds (dog) table are locked when hounds_in_stock_cur is opened:
CURSOR hounds_in_stock_cur IS
SELECT pet.stock_no, pet.breeder, dog.size
FROM dog_breeds dog ,inventory pet
WHERE dog.breed = pet.breed
AND dog.class = 'HOUND'
FOR UPDATE OF pet.stock_no, pet.breeder;

2.2 The WHERE CURRENT OF clause
UPDATE and DELETE statements can use a WHERE CURRENT OF clause if they reference a cursor declared FOR UPDATE. This syntax indicates that the UPDATE or DELETE should modify the current row identified by the FOR UPDATE cursor. The syntax is:
WHERE CURRENT OF cursor_name;
By using WHERE CURRENT OF, you do not have to repeat the WHERE clause in the SELECT statement. For example:
CURSOR wip_cur IS
SELECT acct_no, enter_date FROM wip
WHERE enter_date < SYSDATE -7
FOR wip_rec IN wip_cur
INSERT INTO acct_log (acct_no, order_date)
VALUES (wip_rec.acct_no, wip_rec.enter_

3 Cursor Variables
A cursor variable is a data structure that points to a cursor object, which in turn points to the cursor's result set. You can use cursor variables to more easily retrieve rows in a result set from client and server programs. You can also use cursor variables to hide minor variations in queries.
The syntax for a REF_CURSOR type is:
TYPE ref_cursor_name IS REF CURSOR
[RETURN record_type];
If you do not include a RETURN clause, then you are declaring a weak REF CURSOR. Cursor variables declared from weak REF CURSORs can be associated with any query at runtime. A REF CURSOR declaration with a RETURN clause defines a "strong" REF CURSOR. A cursor variable based on a strong REF CURSOR can be associated with queries whose result sets match the number and datatype of the record structure after the RETURN at runtime.
To use cursor variables, you must first create a REF_CURSOR type, then declare a cursor variable based on that type.
The following example shows the use of both weak and strong REF CURSORs:
-- Create a cursor type based on the companies
TYPE company_curtype IS REF CURSOR

-- Create the variable based on the REF CURSOR.
company_cur company_curtype;

-- And now the weak, general approach.
TYPE any_curtype IS REF CURSOR;
generic_curvar any_curtype;
The syntax to OPEN a cursor variable is:
OPEN cursor_name FOR select_statement;
FETCH and CLOSE a cursor variable using the same syntax as for explicit cursors. There are a number of restrictions on cursor variables:
?    Cursor variables cannot be declared in a package since they do not have a persistent state.
?    You cannot use the FOR UPDATE clause with cursor variables.
?    You cannot assign NULLs to a cursor variable nor use comparison operators to test for equality, inequality, or nullity.
?    Neither database columns nor collections can store cursor variables.
?    You cannot use RPCs to pass cursor variables from one server to another.
?    Cursor variables cannot be used with the dynamic SQL built-in package DBMS_SQL

PL/SQL is the Oracle's extension to SQL with design features of programming languages. The data manipulation and query statements are included in the procedural units of codes. PL/SQL allows the applications to be written in a PL/SQL procedure or a package and stored at Oracle server, where these PL/SQL codes can be used as shared libraries, or applications, thus enhancing the integration and code reuse. Moreover, the Oracle server pre-compiles PL/SQL codes prior to the actual code execution and thus improving the performance.
The basic PL/SQL code structure is :
?    DECLARE -- optional, which declares and define variables, cursors and user-defined exceptions.
?    BEGIN -- mandatory
- SQL statements
- PL/SQL statements
?    EXCEPTION -- optional, which specifies what actions to take when error occurs.
?    END; -- mandatory
For example, the following PL/SQL code block declares an integer v1, assigns it with value 3 and print out the value.
v1 NUMBER(3);

v1 := 3;
DBMS_OUTPUT.PUT_LINE('v1=' || v1);
Note that DBMS_OUTPUT is an Oracle-supplied PL/SQL package and PUT_LINE is one of the packaged procedures. It displays the values on the SQL*Plus terminal which must be enabled with SET SERVEROUTPUT ON first. To execute this code sample, login into SQL*Plus, and type
v1 NUMBER(3);

v1 := 3;
DBMS_OUTPUT.PUT_LINE('v1= ' || v1);
Note that a PL/SQL block is terminated by a slash / or a line byitself.

Handling Variables
?    Variables must be declared first before the usage. The PL/SQL variables can be a scalar type such as DATE, NUMBER, VARCHAR(2), DATE, BOOLEAN, LONG and CHAR, or a composite type, such array type VARRAY.
?    Only TRUE and FALSE can be assigned to BOOLEAN type of variables.
?    AND, OR, NOT operators can be used to connect BOOLEAN values.
?    % TYPE attribute can be used to define a variable which is of type the same as a database column's type definition.
?    Users can customize the variable types by using TYPE ... IS ... statement.
The following code block illustrates the use of TYPE..IS... and VARRAY. In this sample, a type v_arr is defined as an variable array of maximum 25 elements which are of type NUMBER(3). Then a variable v1 is defined as type v_arr . This sample code also demonstrates the use of %TYPE attribute.
TYPE v_arr IS VARRAY(25) of NUMBER(3);
v1 v_arr;
v_empno employee.empno%TYPE;

v1(2) := 3;
DBMS_OUTPUT.PUT_LINE('The Value of v1(2) = ' || v1(2));
v_empno := 4;
Coding Guidelines
?    Single-line comments are prefixed with two dashes --.
?    Multiple-line comments can be enclosed with the symbols /* and */.
?    Variables and function identifiers can contain up to 30 characters, and should not have the same name as a database column name.
?    Identifiers must begin with an alphanumerical character.
?    SQL functions can be used in PL/SQL.
?    Code blocks can be nested and unqualified variables can locally scoped.
?    It is recommended that variable names are prefixed by v_, and parameter names in procedures/functions are prefixed by _p.
SQL Statements in PL/SQL
The following code block shows how to run DML statements in PL/SQL. Basically they look similar to the SQL. Note that the SELECT statement retrieves the single-row value and store into a variable using INTO clause.
v_sal employee.sal%TYPE;

INSERT INTO employee VALUES (6, 'TOM LEE', 10000);

UPDATE employee SET sal = sal + 5000 WHERE empno = 6;
SELECT sal INTO v_sal FROM employee WHERE empno = 6;
DBMS_OUTPUT.PUT_LINE('Salary increased to ' || v_sal);
DELETE FROM employee WHERE empno = 6;

Control Structures
?    Conditions checking
IF <condition> THEN
[ELSIF <condition> THEN]
[ELSE <condition> THEN]
?    Basic loops.
EXIT WHEN <condition>
?    FOR loop.
FOR counter IN lower_bound .. upper_bound
?    WHILE loop.
WHILE <condition> LOOP
The code samples making use of the control structures will be given in the following.
Writing PL/SQL Procedures/Functions
PL/SQL functions returns a scalar value and PL/SQL procedures return nothing. Both can take zero or more number of parameters as input or output. The special feature about PL/SQL is that a procedure/function argument can be of input (indicating the argument is read-only), output (indicating the argument is write-only) or both (both readable and writable).
For example, the following is a PL/SQL procedure and a function.
PROCEDURE hire_employee (emp_id INTEGER, name VARCHAR2) IS
INSERT INTO employee VALUES (emp_id, name, 1000);
END hire_employee;

min_sal REAL;
max_sal REAL;
SELECT losal, hisal INTO min_sal, max_sal
FROM sals
WHERE job = title;
RETURN (salary >= min_sal) AND (salary <= max_sal);
END sal_ok;

A function is called as part of an expression. For example, the function sal_ok might be called as follows:

IF sal_ok(new_sal, new_title) THEN ...
Writing and Compiling PL/SQL Packages.
A package is a database object that groups logically related PL/SQL types, objects, and subprograms. Packages usually have two parts, a specification and a body, although sometimes the body is unnecessary. The specification is the interface to your applications; it declares the types, variables, constants, exceptions, cursors, and subprograms available for use. The body fully defines cursors and subprograms, and so implements the specification.
Unlike subprograms, packages cannot be called, parameterized, or nested. Still, the format of a package is similar to that of a subprogram:
CREATE PACKAGE name AS -- specification (visible part)
-- public type and object declarations
-- subprogram specifications
END [name];

CREATE PACKAGE BODY name AS -- body (hidden part)
-- private type and object declarations
-- subprogram bodies
-- initialization statements]
END [name];
The specification holds public declarations, which are visible to your application. The body holds implementation details and private declarations, which are hidden from your application. As shown in the following figure, you can think of the specification as an operational interface and of the body as a "black box":

You can debug, enhance, or replace a package body without changing the interface (package specification) to the package body.
For example, we want to create a simple package providing three functions: hire_employee, fire_employee and raise_salary.
First we created the package specification.
CREATE OR REPLACE PACKAGE test AS -- package spec
TYPE list IS VARRAY(25) of NUMBER(3);

PROCEDURE hire_employee (emp_id INTEGER, name VARCHAR2);
PROCEDURE fire_employee (emp_id INTEGER);
PROCEDURE raise_salary (emp_id INTEGER, amount REAL);
END test;
Then we created the package body.
PROCEDURE hire_employee (emp_id INTEGER, name VARCHAR2) IS
INSERT INTO employee VALUES (emp_id, name, 1000);
END hire_employee;

PROCEDURE fire_employee (emp_id INTEGER) IS
DELETE FROM employee WHERE empno = emp_id;
END fire_employee;

PROCEDURE raise_salary (emp_id INTEGER, amount REAL) IS
DBMS_OUTPUT.PUT_LINE('Increase Salary :' || to_char(amou
UPDATE employee SET sal = sal + amount WHERE empno = emp_id;
END raise_salary;
END test;

To compile the package, we can either type them into SQL*Plus terminal. And Oracle server will compile and store the package, or save them into separate files and compile them from SQL*Plus. Assume the package spec is stored in a file named spec, and the body is stored in another file named body. The following shows how to compile the package and make the procedure call at SQL*Plus.

SQL> @spec

SQL> @body

SQL> exec test.raise_salary(1,1000);

Reviews and Comments

PMP, CAPM, PMI is a registered certification mark of the Project Management Institute, Inc

Copyright © www.techfaq360.com 2016

About US | Contact US | Privacy Policy | Terms and Conditions  | Website disclaimer  | Cancellation and Refund Policy  | Shipping & Delivery Policy