All Products
Search
Document Center

PolarDB:DBMS_PIPE

Last Updated:Mar 28, 2026

DBMS_PIPE lets sessions connected to the same database cluster send messages to each other through named pipes.

Note

Do not use DBMS_PIPE with cluster endpoints. Doing so can cause long-running transactions.

Use cases

  • Inter-session debugging: Send debugging information from a trigger or stored procedure to a monitoring session, which reads and displays it in real time.

  • Alerting: Notify another session of an event without requiring it to poll repeatedly.

  • External service interface: Exchange messages with user-written services running outside the database.

Key concepts

Pipe types

Pipes can be created implicitly or explicitly.

  • Implicit pipes: Created automatically when you reference a non-existent pipe name—for example, by passing an unknown name to SEND_MESSAGE. All implicitly created pipes are private.

  • Explicit pipes: Created by calling CREATE_PIPE with a name.

Pipes can be private or public.

  • Private pipes: Accessible only by the creator. Even a superuser cannot access a private pipe created by another user.

  • Public pipes: Accessible by all users that can access the DBMS_PIPE package.

Message flow

Sending a message requires two steps: pack items into the local message buffer with PACK_MESSAGE, then send the buffer contents through a pipe with SEND_MESSAGE.

Receiving a message also requires two steps: retrieve a message from the pipe into the local message buffer with RECEIVE_MESSAGE, then extract individual items from the buffer into program variables with UNPACK_MESSAGE.

Each session maintains separate buffers for sent and received messages. If RECEIVE_MESSAGE is called consecutively, only the message from the last call remains in the buffer. If a pipe contains multiple messages, RECEIVE_MESSAGE retrieves them in first-in-first-out (FIFO) order.

Functions and stored procedures

Function or stored procedureReturn typeDescription
CREATE_PIPE(pipename [, maxpipesize] [, private])INTEGERExplicitly creates a public or private pipe
NEXT_ITEM_TYPEINTEGERReturns the data type code of the next item in the local message buffer
PACK_MESSAGE(item)N/AAdds a data item to the local message buffer
PURGE(pipename)N/ARemoves unreceived messages from an implicitly created pipe
RECEIVE_MESSAGE(pipename [, timeout])INTEGERRetrieves a message from a pipe into the local message buffer
REMOVE_PIPE(pipename)INTEGERDeletes an explicitly created pipe
RESET_BUFFERN/AResets the local message buffer pointer to the beginning
SEND_MESSAGE(pipename [, timeout] [, maxpipesize])INTEGERSends the local message buffer contents through a pipe
UNIQUE_SESSION_NAMEVARCHAR2Returns a name that is unique to the current session
UNPACK_MESSAGE(item OUT)N/ACopies the next item from the local message buffer into a program variable

CREATE_PIPE

CREATE_PIPE explicitly creates a public or private pipe with the specified name.

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

Parameters

ParameterDescription
pipenameName of the pipe
maxpipesizeMaximum capacity of the pipe, in bytes. Default: 8192
privateSet to FALSE to create a public pipe, TRUE to create a private pipe. Default: TRUE
statusReturns 0 on success

Examples

Create a private pipe named messages:

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

Output:

CREATE_PIPE status: 0

Create a public pipe named mailbox with the default capacity:

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

Output:

CREATE_PIPE status: 0

NEXT_ITEM_TYPE

NEXT_ITEM_TYPE returns an integer code identifying the data type of the next item in the local message buffer. Call it after RECEIVE_MESSAGE to inspect items before unpacking them. Returns 0 when no more items remain.

typecode INTEGER NEXT_ITEM_TYPE

Return values

CodeData type
0No more items
9NUMBER
11VARCHAR2
13DATE
23RAW
These type codes are not compatible with Oracle databases. Oracle uses a different numbering sequence for data types.

Example

Pack a NUMBER, VARCHAR2, DATE, and RAW item, send them, then retrieve and inspect each type:

-- Pack and send items
DECLARE
    v_number        NUMBER := 123;
    v_varchar       VARCHAR2(20) := 'Character data';
    v_date          DATE := SYSDATE;
    v_raw           RAW(4) := '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;

Output:

SEND_MESSAGE status: 0
-- Receive and inspect each item's type
DECLARE
    v_number        NUMBER;
    v_varchar       VARCHAR2(20);
    v_date          DATE;
    v_timestamp     TIMESTAMP;
    v_raw           RAW(4);
    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;

Output:

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 adds a data item to the local message buffer of the current session. Call it at least once before calling SEND_MESSAGE.

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

Parameters

ParameterDescription
itemA value of type DATE, NUMBER, VARCHAR2, or RAW. The value is appended to the local message buffer.

PURGE

PURGE removes all unreceived messages from an implicitly created pipe.

PURGE(pipename VARCHAR2)

Parameters

ParameterDescription
pipenameName of the pipe
PURGE works only on implicitly created pipes, not on pipes created with CREATE_PIPE.

Example

Send two messages, receive the first, purge the rest, then confirm the pipe is empty:

-- Send two messages
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;

Output:

SEND_MESSAGE status: 0
SEND_MESSAGE status: 0
-- Receive the first 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);
    DBMS_PIPE.UNPACK_MESSAGE(v_item);
    DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
END;

Output:

RECEIVE_MESSAGE status: 0
Item: Message #1
-- Purge remaining messages
EXEC DBMS_PIPE.PURGE('pipe');
-- Confirm the pipe is empty (status 1 = timeout, no messages available)
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;

Output:

RECEIVE_MESSAGE status: 1

Status code 1 indicates a timeout: no messages remain in the pipe.

RECEIVE_MESSAGE

RECEIVE_MESSAGE retrieves a message from a pipe and loads it into the local message buffer of the current session. The message is removed from the pipe when retrieved—a message can only be received once.

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

Parameters

ParameterDescription
pipenameName of the pipe
timeoutMaximum time to wait for a message, in seconds. Default: 86400000 (1,000 days)

Status codes

Status codeDescription
0Message received successfully
1The operation times out
2Message too large for the buffer
3Operation interrupted
ORA-23322Insufficient privileges to access the pipe

REMOVE_PIPE

REMOVE_PIPE deletes an explicitly created pipe.

status INTEGER REMOVE_PIPE(pipename VARCHAR2)

Parameters

ParameterDescription
pipenameName of the pipe
statusReturns 0 on success. Also returns 0 if the specified pipe does not exist.

Example

Create a pipe, send two messages, receive the first, then remove the pipe:

-- Create a pipe and send two messages
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;

Output:

CREATE_PIPE status : 0
SEND_MESSAGE status: 0
SEND_MESSAGE status: 0
-- Receive the first 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);
    DBMS_PIPE.UNPACK_MESSAGE(v_item);
    DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
END;

Output:

RECEIVE_MESSAGE status: 0
Item: Message #1
-- Remove the pipe (discards all remaining messages)
SELECT DBMS_PIPE.REMOVE_PIPE('pipe') FROM DUAL;

Output:

remove_pipe
-------------
           0
(1 row)
-- Confirm the pipe is gone (status 1 = timeout)
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;

Output:

RECEIVE_MESSAGE status: 1

RESET_BUFFER

RESET_BUFFER resets the local message buffer pointer to the beginning, so subsequent PACK_MESSAGE calls overwrite the existing buffer contents.

RESET_BUFFER

Example

Pack a message for John, reset the buffer, pack a replacement message for Bob, then send:

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;

Output:

SEND_MESSAGE status: 0

The received message contains only the items packed after RESET_BUFFER:

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;

Output:

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

SEND_MESSAGE

SEND_MESSAGE sends the contents of the local message buffer through a named pipe. Call PACK_MESSAGE at least once before calling SEND_MESSAGE.

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

Parameters

ParameterDescription
pipenameName of the pipe
timeoutMaximum time to wait if the pipe is full, in seconds. Default: 86400000 (1,000 days)
maxpipesizeMaximum capacity of the pipe, in bytes. Default: 8192

Status codes

Status codeDescription
0Message sent successfully
1The operation times out
3Operation interrupted
ORA-23322Naming conflict: a pipe with the same name already exists and was created by a different user

UNIQUE_SESSION_NAME

UNIQUE_SESSION_NAME returns a VARCHAR2 name that is unique to the current session. Use it to create session-specific pipe names.

name VARCHAR2 UNIQUE_SESSION_NAME

Return value

ValueDescription
nameA unique name for the current session, for example PG$PIPE$5$2752

Example

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

Output:

Session Name: PG$PIPE$5$2752

UNPACK_MESSAGE

UNPACK_MESSAGE copies the next item from the local message buffer into a program variable. Call RECEIVE_MESSAGE first to load a message into the buffer.

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

Parameters

ParameterDescription
itemAn OUT variable that receives the next item from the buffer. Its type must be compatible with the item's data type.

Comprehensive example

The following example implements a simple mailbox using a public pipe. The mailbox package exposes three procedures: create_mailbox creates a named pipe, add_message packs and sends messages with up to three items, and empty_mailbox reads and displays all messages then removes the pipe.

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;

Create the mailbox. The pipe name is generated by UNIQUE_SESSION_NAME:

EXEC mailbox.create_mailbox;

Output:

Created mailbox: PG$PIPE$13$3940

Any user with access to the mailbox and DBMS_PIPE packages can add messages using that pipe name:

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

Output:

Added message with 3 item(s) to mailbox PG$PIPE$13$3940
Added message with 3 item(s) to mailbox PG$PIPE$13$3940

Read all messages and remove the pipe:

EXEC mailbox.empty_mailbox('PG$PIPE$13$3940');

Output:

****** 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 PG$PIPE$13$3940