Oracle Database: PL/SQL cursor overview, oraclepl

Source: Internet
Author: User

Oracle Database: PL/SQL cursor overview, oraclepl
I. cursor Concept

Literally, it refers to a swimming cursor, which is a handle or pointer pointing to the context area.

When performing the CRUD operation in the PL/SQL block, ORACLE allocates a context zone for it in the memory. The database language used to describe the cursor is the location entity mapped to a row of data in the context result set.

You can use a cursor to access any row of data in the result set. After the cursor points to a row, you can operate on the row of data. Cursors provide an independent method for processing each row of data in a multi-row data query result set. They are a common programming method for designing embedded SQL statements.

In each user session, multiple cursors can be opened at the same time. The maximum number of cursors is defined by the OPEN_CURSORS parameter in the database initialization parameter file.

Cursors can be divided into explicit cursors and implicit cursors.

Ii. Explicit cursor

There are four steps to use an explicit cursor:

Declare/define a cursor
Open cursor
Read data
Close cursor

2.1 declare/define a cursor

Syntax:

CURSOR cursor_name
    [(parameter_dec [, parameter_dec]…)]
      [RETURN datatype]
        IS
          select_statement;
Examples:

DECLARE
  CURSOR c1 RETURN departments% ROWTYPE;-declare C1 cursor

  CURSOR c2 IS-declare C2 cursor and define
    SELECT employee_id, job_id, salary FROM employees
    WHERE salary> 2000;

  CURSOR c1 RETURN departments% ROWTYPE IS-define C1 cursor
    SELECT * FROM departments
    WHERE department_id = 110;

  CURSOR c3 RETURN locations% ROWTYPE;-declare C3 cursor

  CURSOR c3 IS-define C3 cursor
    SELECT * FROM locations
    WHERE country_id = 'JP';

  CURSOR c4 (sal number) IS-declare and define C4 cursor
    SELECT employee_id, job_id, salary FROM employees
    WHERE salary> sal;
BEGIN
  NULL;
END;
Description:

When specifying parameter data types, length constraints cannot be used. For example, the parameters of a C4 cursor cannot be written as number (10,4).

[RETURN datatype] is optional and represents the data returned by the cursor. If you choose, you should strictly match the selection list in select_statement in order and data type. Generally it is record data type (RECORD) or data with "% ROWTYPE".

2.2 Open the cursor
Execute the SELECT statement corresponding to the cursor, put its query result into the work area, and the pointer points to the head of the work area to identify the cursor result set.

grammar:

OPEN cursor_name [(cursor_parameter [[,] actual_cursor_parameter] ...)]
Examples:

OPEN c4 (1300);
2.3 Reading data
Retrieve the data rows in the result set and put them into the specified output variable.

grammar:

FETCH {cursor | cursor_variable |: host_cursor_variable}
  {into_clause | bulk_collect_into_clause [LIMIT numeric_expression]};
When the FETCH statement is executed, one data row is returned at a time, and then the cursor is automatically moved to the next data row. When the last row of data is retrieved, if the FETCH statement is executed again, the operation fails and the cursor attribute% NOTFOUND is set to TRUE. So after each execution of the FETCH statement, check the cursor attribute% NOTFOUND to determine whether the FETCH statement was successfully executed and return a data row to determine whether the corresponding variable has been assigned a value.

Examples:

fetch c4 into eid, jid, sal;
2.4 Close the cursor
After processing the cursor result set data, the cursor should be closed in time to release the system resources occupied by the cursor.

After closing the cursor, you can no longer use the FETCH statement to get the data. The closed cursor can be reopened using the OPEN statement.

grammar:

CLOSE cursor_name;
Complete example 1:

DECLARE
   -Define cursor
   CURSOR c_cursor IS
   SELECT first_name || last_name, Salary FROM EMPLOYEES WHERE rownum <11;

   -Declare variables
   v_ename EMPLOYEES.first_name% TYPE;
   v_sal EMPLOYEES.Salary% TYPE;
BEGIN
  -Open cursor
  OPEN c_cursor;
  -- retrieve data
  FETCH c_cursor INTO v_ename, v_sal;
  -- Data processing
  WHILE c_cursor% FOUND LOOP
     DBMS_OUTPUT.PUT_LINE (v_ename || '---' || to_char (v_sal));
     FETCH c_cursor INTO v_ename, v_sal;
  END LOOP;
  -Close cursor
  CLOSE c_cursor;
END;
Complete example 2:

DECLARE
   -Define RECORD record type
   TYPE emp_record_type IS RECORD (
        f_name employees.first_name% TYPE,
        h_date employees.hire_date% TYPE);
   -Declare record variables
   v_emp_record EMP_RECORD_TYPE;
   -Define the cursor, with parameters and return value
   CURSOR c3 (dept_id NUMBER, j_id VARCHAR2)
      RETURN EMP_RECORD_TYPE
   IS
      SELECT first_name, hire_date FROM employees
      WHERE department_id = dept_id AND job_id = j_id;

BEGIN
   -Open the cursor and pass the parameter value
   OPEN c3 (j_id => 'AD_VP', dept_id => 90);
   LOOP
      FETCH c3 INTO v_emp_record;-get data
      IF c3% FOUND THEN
         DBMS_OUTPUT.PUT_LINE (v_emp_record.f_name || 'employment date is || v_emp_record.h_date);
      ELSE
         DBMS_OUTPUT.PUT_LINE ('The result set has been processed');
         EXIT;-exit the loop after processing
      END IF;
   END LOOP;
   CLOSE c3; --Close the cursor
END;
Three: explicit cursor attributes
The state of the cursor (such as whether it is open, how many rows of data are acquired, etc.) can be obtained using the cursor properties.

The cursor attribute is added after the cursor name in the form of "% attribute name". The explicit cursor attributes are:

Property name Description
% FOUND returns TRUE if the record is successfully obtained, otherwise returns FALSE
% NOTFOUND returns TRUE if the record acquisition fails, otherwise returns FALSE
% ROWCOUNT returns the number of records that have been fetched from the cursor
% ISOPEN returns TRUE if the cursor is open, otherwise returns FALSE
Examples:

DECLARE
   v_empno EMPLOYEES.EMPLOYEE_ID% TYPE;
   v_sal EMPLOYEES.Salary% TYPE;
   -Define cursor
   CURSOR c_cursor IS SELECT EMPLOYEE_ID, Salary FROM EMPLOYEES;
BEGIN
   -Open cursor
   OPEN c_cursor;
   LOOP
      -- retrieve data
      FETCH c_cursor INTO v_empno, v_sal;
      EXIT WHEN c_cursor% NOTFOUND;-If the record is not read, then exit the loop
      IF v_sal <= 1200 THEN
            UPDATE EMPLOYEES SET Salary = Salary + 50 WHERE EMPLOYEE_ID = v_empno;
            DBMS_OUTPUT.PUT_LINE ('Code is' || v_empno || 'Salary updated!');
      END IF;
      DBMS_OUTPUT.PUT_LINE ('Number of records:' || c_cursor% ROWCOUNT);
   END LOOP;
   -Close cursor
   CLOSE c_cursor;
END;
Four: define the record variable based on the cursor
Using the% ROWTYPE attribute can not only define record variables based on tables and views, but also record variables based on cursors. When a record variable is defined based on a cursor, the record member name is actually the column name and column alias of the SELECT statement.

In order to simplify the data processing of explicit cursors, it is recommended to use cursor-based record variables to store cursor data. Defining record variables based on cursors is more convenient than declaring record type variables, and is not prone to errors.

Examples:

DECLARE
   -Define cursor
   CURSOR emp_cursor IS SELECT ename, sal FROM emp;
   emp_reocrd emp_cursor% ROWTYPE;-cursor variable
BEGIN
   -Open cursor
   OPEN emp_cursor;
   LOOP
      -Get records
      FETCH emp_cursor INTO emp_record;
      EXIT WHEN emp_record% NOTFOUND;
      dbms_ouput.put_line ('Employee name:' || emp_record.ename || ', employee salary:' || emp_record.sal);
   END LOOP;
   -Close cursor
   CLOSE emp_cursor;
END;
Five: implicit cursor
If a SELECT statement is used in the PL / SQL block to operate, PL / SQL will implicitly process the cursor definition, and for non-query statements, such as modify and delete operations, the ORACLE system automatically sets the cursor for these operations and creates it Workspace. Cursors created implicitly by the system are called implicit cursors, and the name of the implicit cursor is SQL.

For implicit cursor operations, such as definition, open, value, and close operations, are automatically completed by the ORACLE system, without user processing. The user can only complete the corresponding operation through the relevant attributes of the implicit cursor. In the workspace of the implicit cursor, the data stored is the data contained in a newly processed SQL statement that has nothing to do with the user-defined display cursor.

Implicit cursor properties:

Property name Description
SQL% FOUND returns TRUE if the record is successfully obtained, otherwise returns FALSE
SQL% NOTFOUND returns TRUE if the record acquisition fails, otherwise returns FALSE
SQL% ROWCOUNT returns the number of records that have been fetched from the cursor
SQL% ISOPEN returns TRUE if the cursor is open, otherwise returns FALSE
Implicit cursors do not have to be explicitly defined in INSERT, UPDATE, DELETE, SELECT statements.

Examples:

DECLARE
   v_rows NUMBER;

cord emp% ROWTYPE;
        v_name dept.dname% TYPE;
        v_dno emp.deptno% TYPE;
BEGIN
      v_dno: = & no;
      OPEN dept_emp_cursor (v_dno);
      loop
           FETCH dept_emp_cursor INTO v_name, emp_cursor;
           EXIT WHEN dept_emp_cursor% NOTFOUND;
           dbms_output.put_line ('Department name:' || v_name);
           LOOP
               FETCH emp_cursor INTO emp_record;
               EXIT WHEN emp_cursor% NOTFOUND;
               dbms_output.put_line ('employee name:' || emp_record.ename || ', salary:' || emp_record.sal);
           END LOOP;
      end loop;
      CLOSE dept_emp_cursor;
END;

BEGIN
   -Update table data
   UPDATE employees SET salary = 5000 WHERE department_id = 90 AND job_id = 'AD_VP';
   -Get the number of affected rows
   v_rows: = SQL% ROWCOUNT;
   DBMS_OUTPUT.PUT_LINE ('updated' || v_rows || 'employee's salary');
END;
Six: cursor FOR loop
Cursor FOR loop and a quick way to display the cursor, it uses the FOR loop to read the row data in the result set in turn, when the FOR loop begins, the cursor is automatically opened (no OPEN is required), the system automatically reads once every loop Take the data of the current row of the cursor (without FETCH). When exiting the FOR loop, the cursor is automatically closed (without using CLOSE). When using the cursor FOR loop, you cannot use the OPEN statement, FETCH statement, and CLOSE statement, otherwise an error will occur.

grammar:

FOR index_variable IN cursor_name [(value [, value]…)] LOOP
    -Cursor processing statements
END LOOP;
Examples:

DECLARE
    CURSOR emp_cur (vartype number) IS
        SELECT emp_no, emp_zc FROM cus_emp_basic WHERE com_no = vartype;
BEGIN
    FOR person IN emp_cur (123) LOOP
        DBMS_OUTPUT.PUT_LINE ('number:' || person.emp_no || ', address:' || person.emp_zc);
END LOOP;
END;
Seven: Use the display cursor to modify the data
UPDATE and DELETE statements can still be used to update or delete data rows in PL / SQL. Explicit cursors are only used when you need to obtain multiple rows of data. PL / SQL provides a method to delete or update records using only cursors.

The WHERE CURRENT OF clause in an UPDATE or DELETE statement specifically deals with the most recent data fetched from a table to perform an UPDATE or DELETE operation. To use this method, you must use the FOR UPDATE clause when declaring the cursor. When you use the FOR UPDATE clause to open a cursor, all rows in the returned set will be in row-level (ROW-LEVEL) exclusive lock, other objects Can query these data rows, can not perform UPDATE, DELETE or SELECT ... FOR UPDATE operation.

grammar:

FOR UPDATE [OF [schema.] Table.column [, [schema.] Table.column] ..
[NOWAIT]
In a multi-table query, the OF clause is used to lock a specific table. If the OF clause is omitted, all selected data rows in the table will be locked. If these data rows have been locked by other sessions, ORACLE will normally wait until the data rows are unlocked. When the NOWAIT clause is added, if these lines are really locked by another session, OPEN returns immediately and gives:

ORA-00054: resource busy and acquire with nowait specified.
The syntax for using the WHERE CURRENT OF substring in UPDATE and DELETE is as follows:

WHERE {CURRENT OF cursor_name | search_condition}
Examples:

DELCARE
    CURSOR c1 IS
        SELECT empno, salary FROM emp
        WHERE comm IS NULL
        FOR UPDATE OF comm;
    v_comm NUMBER (10,2);
BEGIN
    FOR r1 IN c1 LOOP
        IF r1.salary <500 THEN
            v_comm: = r1.salary * 0.25;
ELSEIF r1.salary <1000 THEN
            v_comm: = r1.salary * 0.20;
ELSEIF r1.salary <3000 THEN
            v_comm: = r1.salary * 0.15;
        ELSE
            v_comm: = r1.salary * 0.12;
        END IF;
        UPDATE emp SET comm = v_comm WHERE CURRENT OF c1;
    END LOOP;
END
Eight: cursor variable
Similar to cursors, cursor variables point to the current row of the result set of a multi-row query. However, cursors and cursor variables are different, just like the relationship between constants and variables. The cursor is static, and the cursor variable is dynamic because it is not tied to a specific query.

8.1 Declare cursor variables
grammar:

TYPE ref_type_name IS REF CURSOR
    [RETURN return_type];
Description:

There are two types of cursor variable types: strong type definition and weak type definition. The strong type definition must specify the return value type of the cursor variable, while the weak type definition does not specify the return value type.

return_type is the return value type of the cursor variable, it must be a record variable.

Examples:

-Define a REF CURSOU type
TYPE ref_cursor_type IS REF CURSOR;
-Declare a cursor variable
cv_ref REF_CURSOR_TYPE;
8.2 Use of cursor variables
Like cursors, cursor variable operations also include three steps: open, extract, and close.

8.2.1 Open cursor variable
grammar:

OPEN {cursor_variable_name |: host_cursor_variable_name}
FOR select_statement;
Description:

host_cursor_variable_name is the cursor variable declared in the PL / SQL host environment (such as OCI: ORACLE Call Interface, Pro * c program, etc.)

The OPEN ... FOR statement can reopen the cursor variable before closing the current cursor variable without causing a CURSOR_ALREAD_OPEN exception error. When the cursor variable is newly opened, the memory processing area of the previous query will be released.

8.2.2 Extracting data
grammar:

FETCH {cursor_variable_name |: host_cursor_variable_name}
INTO {variable [, variable]… | record_variable};
Description:

Put the extracted data into common variables and record variables for storage.

8.2.3 Close the cursor
grammar:

CLOSE {cursor_variable_name |: host_cursor_variable_name}
Description:

If the application attempts to close an unopened cursor variable, it will cause an INVALID_CURSOR exception error.

Example 1:

DECLARE
TYPE ref_type_table IS REF CURSOR;
v_cursor ref_type_table;
emp_record emp% rowtype;
BEGIN
     OPEN v_cursor FOR select * from emp where deptno = & no;
     LOOP
         FETCH v_cursor INTO emp_record;
         EXIT WHEN v_cursor% NOTFOUND;
         dbms_output.put_line ('Employee number:' || emp_record.ename || 'Department number:' || emp_record.deptno);
     END LOOP;
     CLOSE v_cursor;
END;
Example 2:

DECLARE
    emp_record emp% rowtype;
    TYPE ref_type_table IS REF CURSOR RETURN emp% rowtype;
    v_cursor ref_type_table;
BEGIN
     OPEN v_cursor FOR select * from emp where deptno = & no;
     LOOP
         FETCH v_cursor INTO emp_record;
         EXIT WHEN v_cursor% NOTFOUND;
         dbms_output.put_line ('Employee number:' || emp_record.ename || 'Department number:' || emp_record.deptno);
     END LOOP;
     CLOSE v_cursor;
END;

DECLARE
Type emp_record_type IS RECORD (
       ename emp.ename% TYPE,
       salary emp.sal% TYPE,
       deptno emp.deptno% TYPE);
emp_record emp_record_type;

TYPE ref_type_table IS REF CURSOR RETURN emp_record_type;
v_cursor ref_type_table;
BEGIN
     OPEN v_cursor FOR select ename, sal, deptno from emp where deptno = & no;
     LOOP
         FETCH v_cursor INTO emp_record;
         EXIT WHEN v_cursor% NOTFOUND;
         dbms_output.put_line ('employee number:' || emp_record.ename || ', department number:' || emp_record.deptno || ', salary:' || emp_record.salary);
     END LOOP;
     CLOSE v_cursor;
END;
Nine: use cursor to get in batch
grammar:

FETCH ... BULK COLLECT INTO ... [LIMIT row_number];
Description:

Using BULK COLLECT, we can use one back and forth to the database to return multiple rows of data. BULK COLLECT reduces the number of context switches between PL / SQL and SQL engines, thus accelerating the speed of data acquisition.

Examples:

DECLARE
     CURSOR emp_cursor (v_deptno number) IS SELECT * FROM EMP WHERE deptno = v_deptno;
     TYPE type_emp_table IS TABLE OF emp% ROWTYPE INDEX BY BINARY_INTEGER;
     emp_table type_emp_table;
     v_dno emp.deptno% TYPE;
BEGIN
     v_dno: = & no;
     OPEN emp_cursor (v_dno);
     FETCH emp_cursor BULK COLLECT INTO emp_table;
     CLOSE emp_cursor;
     FOR i IN 1..emp_table.COUNT LOOP
         dbms_output.put_line ('employee number:' || emp_table (i) .ename || 'salary:' || emp_table (i) .sal);
     END LOOP;
     CLOSE emp_cursor;
END;
Ten: cursor expression
Cursor expressions are used to return nested cursors. grammar:

CURSOR (sub_query)
Examples:

DECLARE
       CURSOR dept_emp_cursor (v_deptno number) IS
   SELECT dname, cursor (SELECT * FROM emp e WHERE e.deptno = d.deptno)
   FROM dept d WHERE deptno = v_deptno;
       TYPE emp_cursor_type IS REF CURSOR;
       emp_cursor emp_cursor_type;
       emp_re

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.