DBMS_PIPE

您可以使用DBMS_PIPE包在连接到相同数据库集群的会话内部或者会话之间传递消息。

说明

DBMS_PIPE不建议集群地址使用,可能引起长事务问题。

下表列出了DBMS_PIPE包允许使用的函数和存储过程。

表 1. DBMS_PIPE函数/存储过程

函数/存储过程

返回类型

描述

CREATE_PIPE(pipename [, maxpipesize ] [, private ])

INTEGER

使用指定的名称显式地创建一个公有或私有管道。

NEXT_ITEM_TYPE

INTEGER

返回缓冲区中下一个数据成员的数据类型。

PACK_MESSAGE(item)

N/A

将一个数据项放入会话的本地消息缓冲区中。

PURGE(pipename)

N/A

从指定的隐式管道中删除未接收到的消息。

RECEIVE_MESSAGE(pipename [, timeout ])

INTEGER

从指定的管道中获取一条消息。

REMOVE_PIPE(pipename)

INTEGER

删除一个显式的私有或公有管道。

RESET_BUFFER

N/A

清除本地缓冲区的消息。

SEND_MESSAGE(pipename [, timeout ] [, maxpipesize ])

INTEGER

从会话的本地消息缓冲区中将一条消息发送到指定的管道。

UNIQUE_SESSION_NAME

VARCHAR2

返回当前会话的一个唯一名称。

UNPACK_MESSAGE(item OUT)

N/A

将本地消息缓冲区中消息的数据项复制到程序变量中。

  • 创建管道方式分为显式创建和隐式创建。

    • 隐式创建:引用一个之前不是由函数CREATE_PIPE创建的管道名称,会隐式地创建一个管道。例如:如果在执行函数SEND_MESSAGE时使用了一个之前不存在的管道名称,那么就用这个名称隐式地创建一个管道。

      说明

      所有隐式创建的管道均为私有管道。

    • 显式创建:将CREATE_PIPE函数的第一个参数指定为新管道的名称,您可以显式地创建一个管道。

  • 管道分为私有管道和公有管道。

    • 只有创建管道的用户才能访问一个私有管道,超级用户不能访问由其他用户创建的管道。

    • 任何能够访问DBMS_PIPE包的用户均可以访问公有管道。

  • 通过管道发送消息和接受消息。

    • 通过管道发送消息。第一次在本地消息缓冲区创建的单独数据项或者消息文本行,对于当前会话来说是唯一的。您可以使用存储过程PACK_MESSAGE在会话的本地消息缓冲区中创建消息,使用函数SEND_MESSAGE通过管道发送消息。

    • 通过管道接收消息。您首先使用函数RECEIVE_MESSAGE从指定的管道中获得消息,再将消息写到会话的本地缓冲区中。然后使用存储过程UNPACK_MESSAGE将消息的数据成员从消息缓冲区传递给程序变量。如果管道包含多条消息,函数RECEIVE_MESSAGE以先进先出的顺序接收消息。

    存储过程PACK_MESSAGE创建的消息和函数RECEIVE_MESSAGE获取的消息,每一个会话为这两种消息分别保持各自不同的消息缓冲区。可以在相同的会话中创建和接收消息。然而,如果连续执行RECEIVE_MESSAGE函数, 只有最后一次执行RECEIVE_MESSAGE函数所获取的消息会保留在本地消息缓冲区中。

使用说明

CREATE_PIPE

语法说明

函数CREATE_PIPE使用指定的名称显式地创建一个公有或私有管道。语法如下:

status INTEGER CREATE_PIPE(pipename VARCHAR2
  [, maxpipesize INTEGER ] [, private BOOLEAN ])

参数

参数名称

参数说明

pipename

管道的名称。

maxpipesize

管道的最大容量,以字节为单位。默认值为8192 字节。

private

  • TRUE(默认):创建私有管道。

  • FALSE:创建公有管道。

status

创建管道操作返回的状态代码。0表示成功创建。

示例

  • 创建一个名称为messages的私有管道:

    DECLARE
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.CREATE_PIPE('messages');
        DBMS_OUTPUT.PUT_LINE('CREATE_PIPE status: ' || v_status);
    END;

    返回结果如下:

    CREATE_PIPE status: 0
  • 创建一个名称为mailbox的公有管道:

    DECLARE
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.CREATE_PIPE('mailbox',8192,FALSE);
        DBMS_OUTPUT.PUT_LINE('CREATE_PIPE status: ' || v_status);
    END;

    返回结果如下:

    CREATE_PIPE status: 0

NEXT_ITEM_TYPE

语法说明

函数NEXT_ITEM_TYPE返回一个整数型代码,用于标识消息中下一个数据成员的数据类型。其中,消息应已经送到会话的本地缓冲区中。当您使用存储过程UNPACK_MESSAGE从本地消息缓冲区移出每一个数据成员时,函数NEXT_ITEM_TYPE将返回下一个成员的数据类型代码。当在消息中没有成员的时候,将返回代码0。语法如下:

typecode INTEGER NEXT_ITEM_TYPE

参数

参数名称

参数说明

typecode

标识消息中下一个数据项的数据类型。详情请参见NEXT_ITEM_TYPE函数返回代码

表 2. NEXT_ITEM_TYPE函数返回代码

返回代码

描述

0

没有数据成员。

9

NUMBER

11

VARCHAR2

13

DATE

23

RAW

说明

表中列出的代码类型与Oracle不兼容。Oracle给数据类型分配了一个不同的编号序列。

示例

  1. 以下示例显示了一个管道,这个管道填充了一个NUMBER类型的成员,一个VARCHAR2成员、一个DATE成员和一个RAW成员。

    DECLARE
        v_number        NUMBER := 123;
        v_varchar       VARCHAR2(20) := 'Character data';
        v_date          DATE := SYSDATE;
        v_raw           RAW(10) := '21222324';
        v_status        INTEGER;
    BEGIN
        DBMS_PIPE.PACK_MESSAGE(v_number);
        DBMS_PIPE.PACK_MESSAGE(v_varchar);
        DBMS_PIPE.PACK_MESSAGE(v_date);
        DBMS_PIPE.PACK_MESSAGE(v_raw);
        v_status := DBMS_PIPE.SEND_MESSAGE('datatypes');
        DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
    EXCEPTION
        WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
            DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
    END;

    返回结果如下:

    SEND_MESSAGE status: 0
  2. 使用函数NEXT_ITEM_TYPE显示上个示例中每个成员的类型代码。

    DECLARE
        v_number        NUMBER;
        v_varchar       VARCHAR2(20);
        v_date          DATE;
        v_timestamp     TIMESTAMP;
        v_raw           RAW(10);
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.RECEIVE_MESSAGE('datatypes');
        DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
        DBMS_OUTPUT.PUT_LINE('----------------------------------');
    
        v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
        DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
        DBMS_PIPE.UNPACK_MESSAGE(v_number);
        DBMS_OUTPUT.PUT_LINE('NUMBER Item   : ' || v_number);
        DBMS_OUTPUT.PUT_LINE('----------------------------------');
        v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
        DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
        DBMS_PIPE.UNPACK_MESSAGE(v_varchar);
        DBMS_OUTPUT.PUT_LINE('VARCHAR2 Item : ' || v_varchar);
        DBMS_OUTPUT.PUT_LINE('----------------------------------');
    
        v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
        DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
        DBMS_PIPE.UNPACK_MESSAGE(v_date);
        DBMS_OUTPUT.PUT_LINE('DATE Item     : ' || v_date);
        DBMS_OUTPUT.PUT_LINE('----------------------------------');
    
        v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
        DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
        DBMS_PIPE.UNPACK_MESSAGE(v_raw);
        DBMS_OUTPUT.PUT_LINE('RAW Item      : ' || v_raw);
        DBMS_OUTPUT.PUT_LINE('----------------------------------');
    
        v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
        DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
        DBMS_OUTPUT.PUT_LINE('---------------------------------');
    EXCEPTION
        WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
            DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
    END;

    返回结果如下:

    RECEIVE_MESSAGE status: 0
    ----------------------------------
    NEXT_ITEM_TYPE: 9
    NUMBER Item   : 123
    ----------------------------------
    NEXT_ITEM_TYPE: 11
    VARCHAR2 Item : Character data
    ----------------------------------
    NEXT_ITEM_TYPE: 13
    DATE Item     : 02-OCT-07 11:11:43
    ----------------------------------
    NEXT_ITEM_TYPE: 23
    RAW Item      : 21222324
    ----------------------------------
    NEXT_ITEM_TYPE: 0

PACK_MESSAGE

语法说明

PACK_MESSAGE函数将一个数据项放入会话的本地消息缓冲区中。在使用函数SEND_MESSAGE前,必须至少执行一次函数PACK_MESSAGE。语法如下:

PACK_MESSAGE(item { DATE | NUMBER | VARCHAR2 | RAW })

参数

参数名称

参数说明

item

用于计算任何可接受数据类型的参数。计算完毕后,会将结果值添加到会话的本地消息缓冲区中。

示例

该示例展示了如何通过该存储过程发送不同类型的消息。

说明

该部分只是消息发送的部分,消息接收的部分可以查看UNPACK_MESSAGE的示例。

DECLARE
    str      VARCHAR2 := 'Character data';
    num      NUMBER := '1024';
    status   INTEGER;
BEGIN
    DBMS_PIPE.PACK_MESSAGE(str);
    DBMS_PIPE.PACK_MESSAGE(num);
    
    -- send message存储过程
    status := DBMS_PIPE.SEND_MESSAGE('messages');
END;

PURGE

语法说明

存储过程PURGE从指定的隐式管道中删除未接收到的消息。语法如下:

PURGE(pipename VARCHAR2)

参数

参数名称

参数说明

pipename

管道的名称。

示例

  1. 在一个管道上发送两条消息:

    DECLARE
        v_status        INTEGER;
    BEGIN
        DBMS_PIPE.PACK_MESSAGE('Message #1');
        v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
        DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
    
        DBMS_PIPE.PACK_MESSAGE('Message #2');
        v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
        DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
    END;

    返回结果如下:

    SEND_MESSAGE status: 0
    SEND_MESSAGE status: 0
  2. 接收第一条消息,然后打开:

    DECLARE
        v_item          VARCHAR2(80);
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
        DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
        DBMS_PIPE.UNPACK_MESSAGE(v_item);
        DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
    END;

    返回结果如下:

    RECEIVE_MESSAGE status: 0
    Item: Message #1
  3. 删除管道中的消息:

    EXEC DBMS_PIPE.PURGE('pipe');

    此时当您尝试取出下一条消息时,函数RECEIVE_MESSAGE会返回状态代码。

    DECLARE
        v_item          VARCHAR2(80);
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
        DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
    END;

    返回结果如下,1表示超时,因为这时在管道中没有消息:

    RECEIVE_MESSAGE status: 1

RECEIVE_MESSAGE

语法说明

函数RECEIVE_MESSAGE从指定的管道中获取一条消息。语法如下:

status INTEGER RECEIVE_MESSAGE(pipename VARCHAR2
  [, timeout INTEGER ])

参数

参数名称

参数说明

pipename

管道的名称。

timeout

等待时间。单位:秒。默认为86400000 s(表示1000 天)。

表 3. RECEIVE_MESSAGE函数返回的状态代码

状态代码

描述

0

成功获取消息。

1

超时。

2

对于缓冲区来说管道中的消息太大。

3

中断。

ORA-23322

您没有权限获取管道中的消息。

REMOVE_PIPE

语法说明

函数REMOVE_PIPE删除一个显式的私有或公有管道。语法如下:

status INTEGER REMOVE_PIPE(pipename VARCHAR2)

参数

参数名称

参数说明

pipename

管道的名称。

status

函数返回的状态代码。即使命名的管道不存在,也会返回状态代码0。

示例

  1. 在管道中发送两条消息:

    DECLARE
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.CREATE_PIPE('pipe');
        DBMS_OUTPUT.PUT_LINE('CREATE_PIPE status : ' || v_status);
    
        DBMS_PIPE.PACK_MESSAGE('Message #1');
        v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
        DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
    
        DBMS_PIPE.PACK_MESSAGE('Message #2');
        v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
        DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
    END;

    返回结果如下:

    CREATE_PIPE status : 0
    SEND_MESSAGE status: 0
    SEND_MESSAGE status: 0
  2. 接收第一条消息,然后打开:

    DECLARE
        v_item          VARCHAR2(80);
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
        DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
        DBMS_PIPE.UNPACK_MESSAGE(v_item);
        DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
    END;

    返回结果如下:

    RECEIVE_MESSAGE status: 0
    Item: Message #1
  3. 删除管道:

    SELECT DBMS_PIPE.REMOVE_PIPE('pipe') FROM DUAL;

    返回结果如下:

    remove_pipe
    -------------
               0
    (1 row)

    当您尝试取回下一条消息,函数RECEIVE_MESSAGE 将返回状态代码1,表示超时,这是因为管道已经删除。

    DECLARE
        v_item          VARCHAR2(80);
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
        DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
    END;

    返回结果如下:

    RECEIVE_MESSAGE status: 1

RESET_BUFFER

语法说明

存储过程RESET_BUFFER将会话的本地消息缓冲区中的指针重新设置到缓冲区的开始位置。这样在随后调用PACK_MESSAGE时,将覆盖在调用存储过程RESET_BUFFER前在消息缓冲区中已存在的数据项。语法如下:

RESET_BUFFER

示例

  1. 将发给John的消息写到本地消息缓冲区中。调用存储过程RESET_BUFFER后,这条信息被发给Bob的消息覆盖。

    DECLARE
        v_status        INTEGER;
    BEGIN
        DBMS_PIPE.PACK_MESSAGE('Hi, John');
        DBMS_PIPE.PACK_MESSAGE('Can you attend a meeting at 3:00, today?');
        DBMS_PIPE.PACK_MESSAGE('If not, is tomorrow at 8:30 ok with you?');
        DBMS_PIPE.RESET_BUFFER;
        DBMS_PIPE.PACK_MESSAGE('Hi, Bob');
        DBMS_PIPE.PACK_MESSAGE('Can you attend a meeting at 9:30, tomorrow?');
        v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
        DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
    END; 

    返回结果如下:

    SEND_MESSAGE status: 0   
  2. 在接收到的消息中出现了发给Bob的消息。

    DECLARE
        v_item          VARCHAR2(80);
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
        DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
        DBMS_PIPE.UNPACK_MESSAGE(v_item);
        DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
        DBMS_PIPE.UNPACK_MESSAGE(v_item);
        DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
    END;

    返回结果如下:

    RECEIVE_MESSAGE status: 0
    Item: Hi, Bob
    Item: Can you attend a meeting at 9:30, tomorrow?

SEND_MESSAGE

语法说明

函数SEND_MESSAGE从会话的本地消息缓冲区中将一条消息发送到指定的管道。语法如下:

status SEND_MESSAGE(pipename VARCHAR2 [, timeout INTEGER ]
  [, maxpipesize INTEGER ])

参数

参数名称

参数说明

pipename

管道的名称。

timeout

等待时间,以秒为单位。 默认值为86400000 s(表示1000 天)。

maxpipesize

管道的最大容量,以字节为单位。默认值为8192 字节。

表 4. SEND_MESSAGE函数返回的状态代码

状态代码

描述

0

发送消息成功。

1

超时。

3

中断。

ORA-23322

权限不足。

说明

如果存在同名管道且该管道是由不同用户创建的,则Oracle会发出错误信号ORA-23322,指示命名冲突。

示例

该示例用于展示如何将本地的数据发送到管道。

DECLARE
    varchar       VARCHAR2 := 'Character data';
    status        INTEGER;
    result        VARCHAR2;
    idx           INTEGER;
BEGIN
    DBMS_PIPE.PACK_MESSAGE(varchar);
    DBMS_PIPE.PACK_MESSAGE(varchar);
    DBMS_PIPE.PACK_MESSAGE(varchar);
    
    status := DBMS_PIPE.SEND_MESSAGE('messages');
    DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status is: ' || status);
    
    status := DBMS_PIPE.RECEIVE_MESSAGE('messages');

    FOR idx in 1..3 LOOP
      DBMS_PIPE.UNPACK_MESSAGE(result);
      DBMS_OUTPUT.PUT_LINE(result);
    END LOOP;
END;

返回结果如下:

None:  SEND_MESSAGE status is: 0
None:  Character data
None:  Character data
None:  Character data

UNIQUE_SESSION_NAME

语法说明

函数UNIQUE_SESSION_NAME返回当前会话的一个唯一名称。语法如下:

name VARCHAR2 UNIQUE_SESSION_NAME

参数

参数名称

参数说明

name

会话的唯一名称。

示例

DECLARE
    v_session       VARCHAR2(30);
BEGIN
    v_session := DBMS_PIPE.UNIQUE_SESSION_NAME;
    DBMS_OUTPUT.PUT_LINE('Session Name: ' || v_session);
END;

返回结果如下:

Session Name: DBMS_PIPE$35749$

UNPACK_MESSAGE

语法说明

存储过程UNPACK_MESSAGE将本地消息缓冲区中消息的数据项复制到程序变量中。使用UNPACK_MESSAGE前,必须先使用函数RECEIVE_MESSAGE将消息放到本地消息缓冲区中。语法如下:

UNPACK_MESSAGE(item OUT { DATE | NUMBER | VARCHAR2 | RAW })

参数

参数名称

参数说明

item

从本地缓冲区中接收数据项的变量,这个变量必须和数据项的类型相兼容。

示例

该示例展示了如何接收管道中的消息。

DECLARE
    str      VARCHAR2;
    num      NUMBER;
    status   INTEGER;
BEGIN
    -- RECEIVE_MESSAGE status is: 0  
    status := DBMS_PIPE.RECEIVE_MESSAGE('messages');
    DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status is: ' || status);

    -- VARCHAR2 item is: Character data
    DBMS_PIPE.UNPACK_MESSAGE(str);
    DBMS_OUTPUT.PUT_LINE('VARCHAR2 item is: ' || str);

    -- NUMBER item is: 1024
    DBMS_PIPE.UNPACK_MESSAGE(num);
    DBMS_OUTPUT.PUT_LINE('NUMBER item is: ' || num);
END;

综合性示例

  1. 在下面的示例中,将一个管道作为一个“邮箱”。使用存储过程创建邮箱,然后在邮箱中增加一条含有多个数据项的信息(最多有3个数据项)。最后显示mailbox包中的全部内容。

    CREATE OR REPLACE PACKAGE mailbox
    IS
        PROCEDURE create_mailbox;
        PROCEDURE add_message (
            p_mailbox   VARCHAR2,
            p_item_1    VARCHAR2,
            p_item_2    VARCHAR2 DEFAULT 'END',
            p_item_3    VARCHAR2 DEFAULT 'END'
        );
        PROCEDURE empty_mailbox (
            p_mailbox   VARCHAR2,
            p_waittime  INTEGER DEFAULT 10
        );
    END mailbox;
    
    CREATE OR REPLACE PACKAGE BODY mailbox
    IS
        PROCEDURE create_mailbox
        IS
            v_mailbox   VARCHAR2(30);
            v_status    INTEGER;
        BEGIN
            v_mailbox := DBMS_PIPE.UNIQUE_SESSION_NAME;
            v_status := DBMS_PIPE.CREATE_PIPE(v_mailbox,1000,FALSE);
            IF v_status = 0 THEN
                DBMS_OUTPUT.PUT_LINE('Created mailbox: ' || v_mailbox);
            ELSE
                DBMS_OUTPUT.PUT_LINE('CREATE_PIPE failed - status: ' ||
                    v_status);
            END IF;
        END create_mailbox;
    
        PROCEDURE add_message (
            p_mailbox   VARCHAR2,
            p_item_1    VARCHAR2,
            p_item_2    VARCHAR2 DEFAULT 'END',
            p_item_3    VARCHAR2 DEFAULT 'END'
        )
        IS
            v_item_cnt  INTEGER := 0;
            v_status    INTEGER;
        BEGIN
            DBMS_PIPE.PACK_MESSAGE(p_item_1);
            v_item_cnt := 1;
            IF p_item_2 != 'END' THEN
                DBMS_PIPE.PACK_MESSAGE(p_item_2);
                v_item_cnt := v_item_cnt + 1;
            END IF;
            IF p_item_3 != 'END' THEN
                DBMS_PIPE.PACK_MESSAGE(p_item_3);
                v_item_cnt := v_item_cnt + 1;
            END IF;
            v_status := DBMS_PIPE.SEND_MESSAGE(p_mailbox);
            IF v_status = 0 THEN
                DBMS_OUTPUT.PUT_LINE('Added message with ' || v_item_cnt ||
                    ' item(s) to mailbox ' || p_mailbox);
            ELSE
                DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE in add_message failed - ' ||
                    'status: ' || v_status);
            END IF;
        END add_message;
    
        PROCEDURE empty_mailbox (
            p_mailbox   VARCHAR2,
            p_waittime  INTEGER DEFAULT 10
        )
        IS
            v_msgno     INTEGER DEFAULT 0;
            v_itemno    INTEGER DEFAULT 0;
            v_item      VARCHAR2(100);
            v_status    INTEGER;
        BEGIN
            v_status := DBMS_PIPE.RECEIVE_MESSAGE(p_mailbox,p_waittime);
            WHILE v_status = 0 LOOP
                v_msgno := v_msgno + 1;
                DBMS_OUTPUT.PUT_LINE('****** Start message #' || v_msgno ||
                    ' ******');
                BEGIN
                    LOOP
                        v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
                        EXIT WHEN v_status = 0;
                        DBMS_PIPE.UNPACK_MESSAGE(v_item);
                        v_itemno := v_itemno + 1;
                        DBMS_OUTPUT.PUT_LINE('Item #' || v_itemno || ': ' ||
                            v_item);
                    END LOOP;
                    DBMS_OUTPUT.PUT_LINE('******* End message #' || v_msgno ||
                        ' *******');
                    DBMS_OUTPUT.PUT_LINE('*');
                    v_itemno := 0;
                    v_status := DBMS_PIPE.RECEIVE_MESSAGE(p_mailbox,1);
                END;
            END LOOP;
            DBMS_OUTPUT.PUT_LINE('Number of messages received: ' || v_msgno);
            v_status := DBMS_PIPE.REMOVE_PIPE(p_mailbox);
            IF v_status = 0 THEN
                DBMS_OUTPUT.PUT_LINE('Deleted mailbox ' || p_mailbox);
            ELSE
                DBMS_OUTPUT.PUT_LINE('Could not delete mailbox - status: '
                    || v_status);
            END IF;
        END empty_mailbox;
    END mailbox;
  2. 第一个存储过程创建了一个公有管道,这个管道的名称是由函数UNIQUE_SESSION_NAME生成。

    EXEC mailbox.create_mailbox;

    返回结果如下:

    None:  Session Name: DBMS_PIPE$35749$
  3. 在同一数据库中使用邮箱名称,任何访问mailbox包和DBMS_PIPE的用户都能够添加消息。

    EXEC mailbox.add_message('DBMS_PIPE$35749$','Hi, John','Can you attend a meeting at 3:00, today?','-- Mary');
    EXEC mailbox.add_message('DBMS_PIPE$35749$','Don''t forget to submit your report','Thanks,','-- Joe');

    返回结果如下:

    Added message with 3 item(s) to mailbox DBMS_PIPE$35749$
    Added message with 3 item(s) to mailbox DBMS_PIPE$35749$
  4. 清空mailbox包中的内容:

    EXEC mailbox.empty_mailbox('DBMS_PIPE$35749$');

    返回结果如下:

    ****** Start message #1 ******
    Item #1: Hi, John
    Item #2: Can you attend a meeting at 3:00, today?
    Item #3: -- Mary
    ******* End message #1 *******
    *
    ****** Start message #2 ******
    Item #1: Don't forget to submit your report
    Item #2: Thanks,
    Item #3: -- Joe
    ******* End message #2 *******
    *
    Number of messages received: 2
    Deleted mailbox DBMS_PIPE$35749$