1. 程式人生 > >《Oracle PL/SQL開發指南》學習筆記31——原始碼除錯——函式和過程(第三部分,並行查詢及管道函式)

《Oracle PL/SQL開發指南》學習筆記31——原始碼除錯——函式和過程(第三部分,並行查詢及管道函式)

 

1. PARALLEL_ENABLE子句(啟用並行查詢以提高效能)

首次接觸,學習一下:

PARALLEL_ENABLE lets you designate a function to support parallel query capabilities. This type  of guarantee requires that a function doesn’t read or write data from external sources, like packages  or database tables. You should consider designating functions as safe for parallel operations to  improve throughput, but the Oracle Database 12c

optimizer may run undesignated functions  when it believes they are safe for parallel operations. Java methods and external C programs are  never deemed safe for parallel operations.  The following function supports parallel SQL operations and merges last name, first name,  and middle initial into a single string:

SQL> CREATE OR REPLACE FUNCTION merge
  2  ( last_name     VARCHAR2
  3  , first_name    VARCHAR2
  4  , middle_initial VARCHAR2 )
  5  RETURN VARCHAR2 PARALLEL_ENABLE IS
  6  BEGIN
  7    RETURN last_name ||', '||first_name||' '||middle_initial;
  8  END;
  9  /

函式已建立。



FULL_NAME
------------------------------
Jane, Moss Wendy
Jane, Royal Elizabeth
Jonah, Gretelz Simon
Nathan, Smith Brian
Potter, Albus Severus
Potter, Ginny
Potter, Harry
Potter, James Sirius
Potter, Lily Luna
Sweeney, Ian M
Sweeney, Matthew
Sweeney, Meaghan
Vizquel, Doreen
Vizquel, Oscar
Ward, Brandt Henry
Ward, Clinton Goeffrey
Winn, Brian
Winn, Randi

已選擇 18 行。

2. PIPELINED子句

首次接觸,學習一下:

The PIPELINED clause provides improved performance when functions return collections, like  varray or table collections. You’ll also note performance improvements when returning system  reference cursors by using the PIPELINED clause. Pipelined functions also let you return aggregate  tables. Aggregate tables act like collections of PL/SQL record structures. They only work in SQL  statements.  This section discusses collection concepts. Chapter 6 covers collections for those new to  PL/SQL. Collections are arrays and lists of scalar and compound variables. Pipelined functions  only work with table or varray collections. These two types of collections are indexed by sequential  numbers. You can also build collections of user-defined SQL object types, which are treated like  single-dimensional arrays of number, strings, or dates.

SQL> ? desc

 DESCRIBE
 --------

 Lists the column definitions for a table, view, or synonym,
 or the specifications for a function or procedure.

 DESC[RIBE] {[schema.]object[@connect_identifier]}


SQL> CREATE OR REPLACE
  2   TYPE numbers AS VARRAY(10) OF NUMBER
  3  /

型別已建立。

SQL> DESC numbers
 numbers VARRAY(10) OF NUMBER

SQL> CREATE OR REPLACE FUNCTION pipelined_numbers
  2  RETURN NUMBERS
  3  PIPELINED IS
  4    list NUMBERS := numbers(0,1,2,3,4,5,6,7,8,9);
  5  BEGIN
  6    FOR i IN 1..list.LAST LOOP
  7      PIPE ROW(list(i));
  8    END LOOP;
  9    RETURN;
 10  END;
 11  /

函式已建立。

SQL> SELECT *
  2  FROM TABLE (pipelined_numbers);

COLUMN_VALUE
------------
           0
           1
           2
           3
           4
           5
           6
           7
           8
           9

已選擇 10 行。

3. 管道函式示例

首次接觸管道函式,學習一下:

1、管道函式即是可以返回行集合(可以使巢狀表nested table 或陣列 varray)的函式,我們可以像查詢物理表一樣查詢它或者將其     賦值給集合變數。    

2、管道函式為並行執行,在普通的函式中使用dbms_output輸出的資訊,需要在伺服器執行完整個函式後一次性的返回給客戶端。如果需要在客戶端    實時的輸出函式執行過程中的一些資訊,在oracle9i以後可以使用管道函式(pipeline function)。     

 3、關鍵字PIPELINED表明這是一個oracle管道函式,oracle管道函式的返回值型別必須為集合,在函式中,PIPE ROW語句被用來返回該集合的單個元素,函式以一個空的RETURN 語句結束,以表明它已經完成。    

4、由於管道函式的併發多管道流式設計以及實時返回查詢結果而去除了中間環節因此可以帶來可觀的效能提升。”

SQL> CREATE OR REPLACE PACKAGE pipelined IS
  2    /* Declare a PL/SQL record and collection type. */
  3    TYPE account_record IS RECORD
  4    ( account     VARCHAR2(10)
  5    , full_name   VARCHAR2(42));
  6    TYPE account_table IS TABLE OF account_record;
  7
  8    /* Declare a pipelined function. */
  9    FUNCTION pf RETURN account_table PIPELINED;
 10  END pipelined;
 11  /

程式包已建立。

SQL> ed
已寫入 file afiedt.buf

  1  CREATE OR REPLACE PACKAGE BODY pipelined IS
  2    -- Implement a pipelined function.
  3    FUNCTION pf
  4    RETURN account_table
  5    PIPELINED IS
  6      /* Declare a collection control and collection variable. */
  7      counter NUMBER := 1;
  8      account ACCOUNT_TABLE := account_table();
  9      /* Define a cursor. */
 10      CURSOR c IS
 11        SELECT   m.account_number
 12        ,        c.last_name || ', '||c.first_name full_name
 13        FROM     member m JOIN contact c ON m.member_id = c.member_id
 14        ORDER BY c.last_name, c.first_name, c.middle_name;
 15    BEGIN
 16      FOR i IN c LOOP
 17        /* Allot space and add values to collection. */
 18        account.EXTEND;
 19        account(counter).account   := i.account_number;
 20        account(counter).full_name := i.full_name;
 21        /* Assign the collection element to the PIPE. */
 22        PIPE ROW(account(counter));
 23        counter := counter + 1;
 24      END LOOP;
 25      RETURN;
 26    END pf;
 27* END pipelined;
SQL> /

程式包體已建立。

SQL> SELECT *
  2   FROM TABLE(pipelined.pf);

ACCOUNT    FULL_NAME
---------- ------------------------------
SLC-000020 Jane, Moss
SLC-000022 Jane, Royal
SLC-000021 Jonah, Gretelz
SLC-000023 Nathan, Smith
SLC-000024 Potter, Albus
SLC-000024 Potter, Ginny
SLC-000024 Potter, Harry
SLC-000024 Potter, James
SLC-000024 Potter, Lily
SJC-000003 Sweeney, Ian
SJC-000003 Sweeney, Matthew
SJC-000003 Sweeney, Meaghan
SJC-000002 Vizquel, Doreen
SJC-000002 Vizquel, Oscar
SLC-000019 Ward, Brandt
SLC-000018 Ward, Clinton
SJC-000001 Winn, Brian
SJC-000001 Winn, Randi

4. 模式級(獨立)管道函式

SQL> ed
已寫入 file afiedt.buf

  1  CREATE OR REPLACE FUNCTION pf
  2  RETURN pipelined.account_table
  3  PIPELINED IS
  4      -- Declare a collection control variable and collection variable.
  5      counter NUMBER := 1;
  6      account PIPELINED.ACCOUNT_TABLE := pipelined.account_table();
  7      -- Define a cursor.
  8      CURSOR c IS
  9        SELECT   m.account_number
 10        ,        c.last_name || ', '||c.first_name full_name
 11        FROM     member m JOIN contact c ON m.member_id = c.member_id
 12        ORDER BY c.last_name, c.first_name, c.middle_name;
 13    BEGIN
 14      FOR i IN c LOOP
 15        account.EXTEND;
 16        account(counter).account   := i.account_number;
 17        account(counter).full_name := i.full_name;
 18        PIPE ROW(account(counter));
 19        counter := counter + 1;
 20      END LOOP;
 21      RETURN;
 22*   END pf;
SQL> /

函式已建立。

SQL> SELECT * FROM TABLE(pf);

ACCOUNT    FULL_NAME
---------- ------------------------------
SLC-000020 Jane, Moss
SLC-000022 Jane, Royal
SLC-000021 Jonah, Gretelz
SLC-000023 Nathan, Smith
SLC-000024 Potter, Albus
SLC-000024 Potter, Ginny
SLC-000024 Potter, Harry
SLC-000024 Potter, James
SLC-000024 Potter, Lily
SJC-000003 Sweeney, Ian
SJC-000003 Sweeney, Matthew
SJC-000003 Sweeney, Meaghan
SJC-000002 Vizquel, Doreen
SJC-000002 Vizquel, Oscar
SLC-000019 Ward, Brandt
SLC-000018 Ward, Clinton
SJC-000001 Winn, Brian
SJC-000001 Winn, Randi

已選擇 18 行。