zoukankan      html  css  js  c++  java
  • pl/sql [Cursor Management] Cursor Packages & Managing Cursor Packages

    Consolidate Cursors and SQL in Packages
    By placing cursors inside packages, you control the use of SQL in your PL/SQL code. This removes the burden of knowledge about complex joins, etc., from individual developers. It also allows you to maintain one area in which database structure changes impact PL/SQL programs.
    It may not be practical, but it is probably worth attempting to perform an advance analysis of all of the programmers’ needs to produce a full set of queries pre-defined in the package.

    1PACKAGE emp_access
    2   IS
    3      CURSOR emp_all ;
    4      CURSOR in_dept_order  ;
    5      CURSOR in_sal_order  ;
    6   END emp_access;
    7

    Declaring Packaged Cursors
    If you are declaring an explicit cursor in a package specification, you have two options:
    Declare the entire cursor, including the query, in the specification. This is exactly the same as if you were declaring a cursor in a local PL/SQL block.
    Declare only the header of the cursor and do not include the query itself. In this case, the query is defined in the package body only . You have, in effect, hidden the implementation of the cursor.
    If you declare only the header, then you must add a RETURN clause to a cursor definition that indicates the data elements returned by a fetch from the cursor. Of course, these data elements are actually determined by the SELECT statement for that cursor, but the SELECT statement appears only in the body, not in the specification.
    The RETURN clause may be made up of either of the following datatype structures:

    A record defined from a database table using the %ROWTYPE attribute
    A record defined from a programmer-defined record
    If you declare a cursor in a package body, the syntax is the same as if you were declaring it in a local PL/SQL block.
    Here is a simple package specification that shows both of these approaches:

    1 CREATE OR REPLACE PACKAGE book_info
    2 IS
    3  CURSOR byauthor_cur (
    4   author_in IN books.author%TYPE
    5  )
    6  IS
    7   SELECT *
    8     FROM books
    9    WHERE author = author_in;
    10
    11  CURSOR bytitle_cur (
    12   title_filter_in IN books.title%TYPE
    13  ) RETURN books%ROWTYPE;
    14
    15  TYPE author_summary_rt IS RECORD (
    16   author books.author%TYPE,
    17   total_page_count PLS_INTEGER,
    18   total_book_count PLS_INTEGER);
    19
    20  CURSOR summary_cur (
    21   author_in IN books.author%TYPE
    22  ) RETURN author_summary_rt;
    23 END book_info;

    On lines 3–9 you can see a very typical explicit cursor definition, fully defined in the package specification. On lines 11–13, I define a cursor without a query. In this case, I am telling whoever is looking at the specification that if they open and fetch from this cursor they will receive a single row from the books table for the specified “title filter,” the implication being that wild cards are accepted in the description of the title. On lines 15–18, I define a new record type to hold summary information for a particular author, and on lines 20–22, I declare a cursor that returns summary information (just three values) for a given author.

    Working with Packaged Cursors
    Now let’s see how you can take advantage of packaged cursors. First of all, you do not need to learn any new syntax to open, fetch from, and close packaged cursors; you just have to remember to prepend the package name to the name of the cursor. So if you want to get information about all the books having to do with PL/SQL, a block can be written like this:

     1DECLARE
     2   onebook book_info.bytitle_cur%ROWTYPE;
     3BEGIN
     4   OPEN book_info.bytitle_cur ('%PL/SQL%');
     5   LOOP
     6      EXIT WHEN book_info.bytitle_cur%NOTFOUND;
     7      FETCH book_info.bytitle_cur INTO onebook;
     8      book_info.display (onebook);
     9   END LOOP;
    10   CLOSE book_info.bytitle_cur;
    11END;

    As you can see, you can %ROWTYPE a packaged cursor and check its attributes just as you would with a locally defined explicit cursor.

    There are some hidden issues lurking in this code, however. Because the cursor is declared in a package specification, its scope is not bound to any given PL/SQL block. Suppose that this code is run:

    1BEGIN -- Only open
    2   OPEN book_info.bytitle_cur ('%PEACE%');
    3END;

    and then, in the same session, the anonymous block with the LOOP shown above is also run. An error will then occur:

    ORA-06511: PL/SQL: cursor already open
    This happened because in the “only open” block, the cursor was not closed. Even though the block terminated, the packaged cursor did not close.

    Given the persistence of packaged cursors, you should always keep the following rules in mind:

    Never assume that a packaged cursor is closed (and ready to be opened).
    Never assume that a packaged cursor is opened (and ready to be closed).
    Always be sure to explicitly close your packaged cursor when you are done with it.
    These three rules also apply to working with other kinds of cursors—such as locally defined explicit cursors and DBMS_SQL cursors—but they are absolutely crucial for packaged cursors.
    If you neglect these rules, you might well execute an application that makes certain assumptions, and then pays the price in unexpected and unhandled exceptions.

  • 相关阅读:
    谈一谈对象池SafeObjectPool能干什么
    .net core 程序退出事件
    .NETCore 快速开发做一个简易商城
    Git创建子分支,合并分支并提交
    Vue项目中关闭eslint的方法
    Missing space before function parentheses
    单引号变双引号 格式化去掉分号
    Docker Swarm搭建多服务器下Docker集群
    Asp.Net Core中服务的生命周期选项区别和用法
    KnockoutJS-模板绑定
  • 原文地址:https://www.cnblogs.com/jimeper/p/1389468.html
Copyright © 2011-2022 走看看