【轉】使用oracle pipe傳遞訊息
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許可權,才能在儲存過程中使用。
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- vue---元件間傳遞訊息(父子傳遞訊息,兄弟傳遞訊息)Vue元件
- Android訊息傳遞之元件間傳遞訊息Android元件
- Flutter中訊息傳遞Flutter
- Chrome Extension 訊息傳遞Chrome
- flutter 訊息傳遞機制Flutter
- Handler訊息傳遞機制
- Apache Kafka訊息傳遞策略ApacheKafka
- Android訊息傳遞之Handler訊息機制Android
- Android訊息傳遞之EventBus 3.0使用詳解Android
- QNX學習 -- API之訊息傳遞API
- C#視窗間傳遞訊息C#
- 在ASP.NET Core 中使用 .NET Aspire 訊息傳遞元件ASP.NET元件
- Spring Boot 參考指南(訊息傳遞)Spring Boot
- Aeron訊息傳遞客戶端--Go版客戶端Go
- Java中用Aeron實現UDP訊息傳遞JavaUDP
- iOS開發筆記(三):訊息傳遞與轉發機制iOS筆記
- Android Handler訊息傳遞機制詳解Android
- objc系列譯文(7.4):訊息傳遞機制OBJ
- Pulsar 入門實戰(1)--Pulsar 訊息傳遞
- Android之Handler訊息傳遞機制詳解Android
- RabbitMQ 和訊息傳遞常用一些術語MQ
- NATS訊息傳遞與REST效能比較 | VinsguruREST
- 基於WebSocket的實時訊息傳遞設計Web
- uc/os-iii學習筆記-訊息傳遞筆記
- 深度解析VC中的訊息傳遞機制(上)
- 深度解析VC中的訊息傳遞機制(下)
- 新增的WebSphere MQ訊息傳遞提供程式簡介WebMQ
- .NET 8 中利用 MediatR 實現高效訊息傳遞
- OC isa結構、訊息傳遞、Method Swizzling
- 執行緒通訊機制:共享記憶體 VS 訊息傳遞執行緒記憶體
- Rabbitmq可靠訊息投遞,訊息確認機制MQ
- 學習在.NET Core中使用RabbitMQ進行訊息傳遞之持久化(二MQ持久化
- 用程式碼理解 ObjC 中的傳送訊息和訊息轉發OBJ
- 用程式碼理解ObjC中的傳送訊息和訊息轉發OBJ
- Go 微服務:基於 RabbitMQ 和 AMQP 進行訊息傳遞Go微服務MQ
- android 訊息傳遞機制進階EventBus的深入探究Android
- Android Handler訊息傳遞機制:圖文解析工作原理Android
- 跨共識訊息格式XCM有幾種傳遞機制?