【轉】使用oracle pipe傳遞訊息

ljm0211發表於2012-06-20
1.管道操作
  1.1管道的通訊機制:   傳送者把訊息傳送到本地訊息緩衝區,本地訊息緩衝區的訊息傳送到指定例項的UGA區域,訊息接收者從資料庫 獲取訊息並且放到本地訊息緩衝區,然後從本地訊息緩衝區讀取訊息。
由於資料庫把管道建立在資料庫例項的UGA,所以管道式可以實現同一個資料庫例項下不同資料庫會話之間的通訊的。
注意:管道訊息是獨立於事務的,也就是說不能回滾得,並且同一個管道訊息只能被一個接收。也就是說要實現訊息的,還需要在管道上的通訊機制上,自己做進一步的工作。
1種方式就是採用迴圈的方式,對需要接收訊息的使用者按照資料庫會話的方式,一個迴圈下來對每一個資料庫會話都傳送一條訊息(按照會話內通訊(訊息的定址)的方式進行處理)。
使用者可以定義自己的來實現管道訊息。參考下面的例子。
較多的訊息的傳送和接收。對於那些需要傳送大的訊息,應該考慮採用資料表的方式,透過管道可以傳送訊息的簡要,真正的訊息內容儲存到一個資料表中去,
當使用者透過管道獲得訊息後,解析訊息,然後去相應的資料表獲取真正的訊息內容。
1.2傳送訊息/接收訊息
---傳送訊息到指定管道
declare
i integer;
j integer;
begin
for j in 1..10loop
dbms_pipe.pack_message('wdz'||j);
end loop;
dbms_pipe.pack_message('end');
i := dbms_pipe.send_message('apple');
if i =0 then
dbms_output.put_line('ok--傳送訊息成功!');

end if;
end;

---從指定管道接受訊息
declare
i integer;
ch varchar2(200);
flag boolean :=false;
begin
i := dbms_pipe.receive_message('apple',100);
if(i=0)then
dbms_output.put_line('ok---準備接受訊息');
else
flag := true;
end if;
while(not flag) loop
dbms_pipe.unpack_message(ch);
if(upper(ch)='END') then
flag := true;
dbms_output.put_line('接收訊息完成');
else
dbms_output.put_line('訊息內容='||ch);
end if;
end loop;
end;

1.3使用自己定義的協議傳送/接收訊息
-- Created on 2003-11-10 by wdz
---傳送訊息到指定管道
---自己定義的訊息協議
---用訊息對的方式傳送和接收訊息。
---訊息對的第一個訊息作為訊息頭表明訊息對的第2個訊息的型別。
---訊息對的第2個訊息表明訊息對的訊息體
--- c 表示訊息體為字元型
--- d 表示訊息體為日期型
--- n 表示訊息體為數字型
declare
i integer;
j integer;
begin

dbms_pipe.pack_message('c');
dbms_pipe.pack_message('訊息體為字元型');
dbms_pipe.pack_message('d');
dbms_pipe.pack_message(sysdate);
dbms_pipe.pack_message('n');
dbms_pipe.pack_message(1000);

dbms_pipe.pack_message('end');
i := dbms_pipe.send_message('apple');
if i =0 then
dbms_output.put_line('ok--傳送訊息成功!');

end if;
end;


---從指定管道接受訊息
---自己定義的訊息協議
---用訊息對的方式傳送和接收訊息。
---訊息對的第一個訊息作為訊息頭表明訊息對的第2個訊息的型別。
---訊息對的第2個訊息表明訊息對的訊息體
--- c 表示訊息體為字元型
--- d 表示訊息體為日期型
--- n 表示訊息體為數字型
declare
i integer;
ch varchar2(200);
ch2 varchar2(200);
msgDate date;
msgNum number;
msgString varchar2(1000);
flag boolean :=false;
begin
i := dbms_pipe.receive_message('apple',100);
if(i=0)then
dbms_output.put_line('ok---準備接受訊息');
else
flag := true;
end if;
while(not flag) loop
dbms_pipe.unpack_message(ch);
if(upper(ch)='END') then
flag := true;
dbms_output.put_line('接收訊息完成');
else
if ch='d' then
dbms_pipe.unpack_message(msgDate);
dbms_output.put_line('日期訊息內容='||to_char(msgDate,'yyyy-mm-dd hh24:mi:ss'));
elsif ch='n' then
dbms_pipe.unpack_message(msgNum);
dbms_output.put_line('數字型訊息內容='||to_char(msgNum));
elsif ch='c' then
dbms_pipe.unpack_message(msgString);
dbms_output.put_line('字元型訊息內容='||msgString);
end if ;
end if;
end loop;
end;

1.4會話內通訊(訊息的定址)
-- Created on 2003-11-10 by wdz
---從在當前資料庫會話內使用管道傳送訊息
declare
i integer;
j integer;
begin
dbms_pipe.pack_message('測試傳送字串訊息');
dbms_pipe.pack_message(sysdate);
dbms_pipe.pack_message(2000);
dbms_pipe.pack_message('最後一條訊息');
---- 使用 dbms_pipe.unique_session_name來指定管道名稱,這樣可以按照資料庫會話來實--現會話內通訊,當然也可以自己來定義1種會話的命名方式,只要能夠名稱按照會話名字唯一--就可以了。
i := dbms_pipe.send_message(dbms_pipe.unique_session_name);
if i =0 then
dbms_output.put_line('ok--傳送訊息成功!');
end if;
end;

---- -- Created on 2003-11-10 by wdz
---從在當前資料庫會話內使用管道接受訊息
---- 使用 dbms_pipe.unique_session_name來指定管道名稱,這樣可以按照資料庫會話來
--實--現會話內通訊,當然也可以自己來定義1種會話的命名方式,只要能夠名稱按照會話名字唯一--就可以了。

declare
i integer;
ch varchar2(1000);
msgDate date;
msgNum number;
msgString varchar2(1000);
flag boolean := false;
begin
i := dbms_pipe.receive_message(dbms_pipe.unique_session_name, 100);
if (i = 0) then
dbms_output.put_line('ok---準備接受訊息');
else
flag := true;
end if;
while (not flag) loop
i := dbms_pipe.next_item_type;
if (i = 0) then
flag := true;
dbms_output.put_line('##接收訊息完成');
elsif i = 12 then-- 12 date
dbms_pipe.unpack_message(msgDate);
dbms_output.put_line('日期訊息內容=' ||to_char(msgDate, 'yyyy-mm-dd hh24:mi:ss'));
elsif i =6 then --6 number
dbms_pipe.unpack_message(msgNum);
dbms_output.put_line('數字型訊息內容=' || to_char(msgNum));
elsif i = 9 then -- 9 varchar2
dbms_pipe.unpack_message(msgString);
dbms_output.put_line('字元型訊息內容=' || msgString);
end if;
end loop;
end;

1.5.執行許可權
擁有DBA許可權的使用者可以在pl/sql 塊訪問dbms_pipe,但是不能在執行。因為該包禁止角色執行。應該是透過dba把dbms_pipe的execute許可權分配給指定使用者。
也就是一個使用者即使是dba也需要獲得dbms_pipe的execute許可權,才能在儲存過程中使用。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/11411056/viewspace-733327/,如需轉載,請註明出處,否則將追究法律責任。

相關文章