`
king_tt
  • 浏览: 2234256 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

利用Oracle dbms_pipe实现存储过程之间的通信

 
阅读更多

应用程序开发人员的需求是这样的:
1. 根据条件给每一个国家的商品生成唯一7位随机代码,不同国家之间的商品代码可以相同
2. 如果输入标准分隔符的字符串,则解析该字符串作为需要生成的商品ID,为其生成代码,否则为商品表中所有商品ID生成代码
3. 代码的每一位要符合相应的规则,例如第一位的规则是[0123],则这位只能是0、1、2、3中的一个数
4. 由于可能一次生成大量的代码,这个过程需要较长时间,所以需要用进度条提示生成进度
5. 可以在生成过程执行中终止过程
6. 返回需要生成的代码个数和实际生成的代码个数
7. 每次提交的个数可以通过参数定义,例如共要生成10万的代码,每次提交1000个

设计思路:
1. 为每个国家预生成0到9999999一千万个随机数作为候选代码池表,每生成一个代码就从代码池中删除一个,避免查重操作
2. 用一个存储过程生成代码,另一个过程用来终止生成过程,两个过程间用dbms_pipe进行通信
3. 用一个函数返回当前已经生成的代码个数,供显示进度条的外部程序调用,生成代码过程与该函数用dbms_pipe进行通信
4. 用bulk collect批量处理提高效率

源代码:

[c-sharp]view plaincopy
  1. --1.生成可用代码池,重复执行过程为每一个国家生成一个可用代码池表,表名为org_code_加上两位国家代码
  2. CREATEORREPLACEPROCEDUREp_org_code
  3. IS
  4. BEGIN
  5. --tmp是一个提交后删除行的全局临时表
  6. FORiIN0..9999999
  7. LOOP
  8. INSERTINTOtmp
  9. VALUES(LPAD(i,7,'0'));
  10. ENDLOOP;
  11. INSERTINTOorg_code_00
  12. SELECT*
  13. FROMtmp
  14. ORDERBYDBMS_RANDOM.VALUE;
  15. COMMIT;
  16. END;
  17. --2.代码生成过程
  18. CREATEORREPLACEPROCEDUREp_gen_code(
  19. p_country_codeINVARCHAR2,--国家代码
  20. p_p1INVARCHAR2,--第一位规则字符串,如012345
  21. p_p2INVARCHAR2,--第二位规则字符串,如012345
  22. p_p3INVARCHAR2,--第三位规则字符串,如012345
  23. p_p4INVARCHAR2,--第四位规则字符串,如012345
  24. p_p5INVARCHAR2,--第五位规则字符串,如012345
  25. p_p6INVARCHAR2,--第六位规则字符串,如012345
  26. p_p7INVARCHAR2,--第七位规则字符串,如012345
  27. p_instrINVARCHAR2,--商品ID字符串,用,做分隔符
  28. p_countINNUMBERDEFAULT1000,--每次提交的个数
  29. r_outstrOUTVARCHAR2--输出需要生成的代码个数和实际生成的代码个数
  30. )
  31. IS
  32. l_idDBMS_SQL.varchar2_table;
  33. l_mcDBMS_SQL.varchar2_table;
  34. l_codeDBMS_SQL.varchar2_table;
  35. l_mc_strVARCHAR2(255);
  36. l_code_strVARCHAR2(7);
  37. l_id_countINT:=0;
  38. l_code_countINT:=0;
  39. l_idxINT;
  40. l_startINT:=1;
  41. l_substrVARCHAR2(32);
  42. l_instrVARCHAR2(2000);
  43. l_lengthINT;
  44. l_tablenameVARCHAR2(30):='org_code_'||p_country_code;
  45. l_sqlVARCHAR2(2000);
  46. l_countINT:=0;
  47. l_pointerINT:=0;
  48. l_real_countINT:=0;
  49. --IPC
  50. l_pipenameCONSTANTVARCHAR2(12):='mypipe';
  51. l_pipe_getcountCONSTANTVARCHAR2(12):='getcount';
  52. l_pipe_retcountCONSTANTVARCHAR2(12):='retcount';
  53. l_send_resultINT;
  54. BEGIN
  55. DBMS_PIPE.PURGE(l_pipename);
  56. IFp_instrISNULL
  57. THEN
  58. BEGIN
  59. SELECTID,mc
  60. BULKCOLLECTINTOl_id,l_mc
  61. FROMproduct;
  62. l_id_count:=l_id.COUNT;
  63. l_sql:=
  64. 'selectcode1from(selectcode1from'
  65. ||l_tablename
  66. ||'whereinstr('''
  67. ||p_p1
  68. ||''',substr(code1,1,1))>0andinstr('''
  69. ||p_p2
  70. ||''',substr(code1,2,1))>0andinstr('''
  71. ||p_p3
  72. ||''',substr(code1,3,1))>0andinstr('''
  73. ||p_p4
  74. ||''',substr(code1,4,1))>0andinstr('''
  75. ||p_p5
  76. ||''',substr(code1,5,1))>0andinstr('''
  77. ||p_p6
  78. ||''',substr(code1,6,1))>0andinstr('''
  79. ||p_p7
  80. ||''',substr(code1,7,1))>0whererownum<='
  81. ||l_id_count;
  82. EXECUTEIMMEDIATEl_sql
  83. BULKCOLLECTINTOl_code;
  84. l_code_count:=l_code.COUNT;
  85. WHILE(l_count<l_code_count)
  86. LOOP
  87. IFDBMS_PIPE.receive_message(l_pipename,0)=0
  88. THEN
  89. DBMS_PIPE.unpack_message(l_pipebuf);
  90. EXITWHENl_pipebuf='stop';
  91. ENDIF;
  92. IFDBMS_PIPE.receive_message(l_pipe_getcount,0)=0
  93. THEN
  94. DBMS_PIPE.PURGE(l_pipe_retcount);
  95. dbms_pipe_pack_message(TO_CHAR(l_count)||'|running');
  96. l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
  97. ENDIF;
  98. l_real_count:=
  99. LEAST(p_count,l_code_count-l_pointer*p_count);
  100. FORiIN1..l_real_count
  101. LOOP
  102. INSERTINTOproduct_code
  103. VALUES(l_code(l_pointer*p_count+i),
  104. l_mc(l_pointer*p_count+i),
  105. p_country_code);
  106. EXECUTEIMMEDIATE'deletefrom'
  107. ||l_tablename
  108. ||'wherecode1=:x'
  109. USINGl_code(l_pointer*p_count+i);
  110. UPDATEproduct
  111. SETstatus=1
  112. WHEREID=l_id(l_pointer*p_count+i);
  113. ENDLOOP;
  114. COMMIT;
  115. l_pointer:=pointer+1;
  116. l_count:=l_count+l_real_count;
  117. ENDLOOP;
  118. DBMS_PIPE.PURGE(l_pipe_retcount);
  119. DBMS_PIPE.pack_message(TO_CHAR(l_count)||'|end');
  120. l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
  121. r_outstr:=l_id_count||'|'||l_count;
  122. DBMS_OUTPUT.put_line(r_outstr);
  123. EXCEPTION
  124. WHENNO_DATA_FOUND
  125. THEN
  126. COMMIT;
  127. WHENOTHERS
  128. THEN
  129. RAISE;
  130. END;
  131. ELSE
  132. IFSUBSTR(p_instr,-1,1)=','
  133. THEN
  134. l_instr:=p_instr;
  135. ELSE
  136. l_instr:=p_instr||',';
  137. ENDIF;
  138. l_length:=LENGTH(l_instr);
  139. <<outer_loop>>
  140. WHILEl_start<l_length
  141. LOOP
  142. l_id_count:=l_id_count+1;
  143. l_idx:=INSTR(l_instr,',',l_start);
  144. l_substr:=SUBSTR(l_instr,l_start,l_idx-l_start);
  145. l_start:=l_idx+1;
  146. IFDBMS_PIPE.receive_message(l_pipename,0)=0
  147. THEN
  148. DBMS_PIPE.unpack_message(l_pipebuf);
  149. EXITWHENl_pipebuf='stop';
  150. ENDIF;
  151. IFDBMS_PIPE.receive_message(l_pipe_getcount,0)=0
  152. THEN
  153. DBMS_PIPE.PURGE(l_pipe_retcount);
  154. DBMS_PIPE.pack_message(l_code_count||'|running');
  155. l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
  156. ENDIF;
  157. BEGIN
  158. SELECTmc
  159. INTOl_mc_str
  160. FROMproduct
  161. WHEREID=l_substr;
  162. EXCEPTION
  163. WHENOTHERS
  164. THEN
  165. GOTOouter_loop;
  166. END;
  167. l_sql:=
  168. 'selectcode1from(selectcode1/*+first_rows*/from'
  169. ||l_tablename
  170. ||'whereinstr('''
  171. ||p_p1
  172. ||''',
  173. substr(code1,1,1))>0andinstr('''
  174. ||p_p2
  175. ||''',
  176. substr(code1,2,1))>0andinstr('''
  177. ||p_p3
  178. ||''',
  179. substr(code1,3,1))>0andinstr('''
  180. ||p_p4
  181. ||''',
  182. substr(code1,4,1))>0andinstr('''
  183. ||p_p5
  184. ||''',
  185. substr(code1,5,1))>0andinstr('''
  186. ||p_p6
  187. ||''',
  188. substr(code1,6,1))>0andinstr('''
  189. ||p_p7
  190. ||''',
  191. substr(code1,1,1))>0)whererownum=1';
  192. BEGIN
  193. EXECUTEIMMEDIATEl_sql
  194. INTOl_code_str;
  195. EXCEPTION
  196. WHENNO_DATA_FOUND
  197. THEN
  198. EXIT;
  199. END;
  200. IFSQL%ROWCOUNT=1
  201. THEN
  202. l_code_count:=l_code_count+1;
  203. ENDIF;
  204. INSERTINTOproduct_code
  205. VALUES(l_code_str,l_wzmc_str,p_country_code);
  206. EXECUTEIMMEDIATE'deletefrom'||l_tablename||'wherecode1=:x'
  207. USINGl_code_str;
  208. UPDATEproduct
  209. SETstatus=1
  210. WHEREID=l_substr;
  211. ENDLOOP;
  212. COMMIT;
  213. DBMS_PIPE.PURGE(l_pipe_retcount);
  214. DBMS_PIPE.pack_message(TO_CHAR(l_code_count)||'|end');
  215. l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
  216. r_outstr:=
  217. LENGTH(l_instr)
  218. -LENGTH(REPLACE(l_instr,',',''))
  219. ||'|'
  220. ||l_code_count;
  221. DBMS_OUTPUT.put_line(r_outstr);
  222. ENDIF;
  223. ENDp_gen_code;
  224. --3.终止过程
  225. CREATEORREPLACEPROCEDUREp_stop
  226. IS
  227. l_pipenameVARCHAR2(12):='mypipe';
  228. l_create_resultINTEGER:=DBMS_PIPE.create_pipe(l_pipename);
  229. l_send_resultINTEGER;
  230. BEGIN
  231. DBMS_PIPE.PURGE(l_pipename);
  232. DBMS_PIPE.pack_message('stop');
  233. l_send_result:=DBMS_PIPE.send_message(l_pipename);
  234. DBMS_OUTPUT.put_line('l_send_result:'||l_send_result);
  235. ENDp_stop;
  236. --4.取得当前已经生成代码的个数
  237. CREATEORREPLACEFUNCTIONfn_getcount(p_timeoutNUMBER)
  238. RETURNVARCHAR2
  239. IS
  240. l_pipebufVARCHAR2(20);
  241. l_pipe_getcountVARCHAR2(12):='getcount';
  242. l_pipe_retcountVARCHAR2(12):='retcount';
  243. l_statusNUMBER;
  244. l_receiveNUMBER;
  245. BEGIN
  246. DBMS_PIPE.PURGE(l_pipe_getcount);
  247. DBMS_PIPE.pack_message(l_pipe_getcount);
  248. l_status:=DBMS_PIPE.send_message(l_pipe_getcount);
  249. l_receive:=
  250. DBMS_PIPE.receive_message(l_pipe_retcount,NVL(p_timeout,0));
  251. IFl_receive=0
  252. THEN
  253. DBMS_PIPE.unpack_message(l_pipebuf);
  254. RETURNTO_CHAR(l_pipebuf);
  255. ELSE
  256. RETURNTO_CHAR('Timedout!');
  257. ENDIF;
  258. ENDfn_getcount;

分享到:
评论

相关推荐

    Oracle系统包详细使用方法

    dbms_pipe包提供了管道通信机制,允许进程间传递数据。dbms_alert则用于发布和接收异步通知。dbms_transaction管理事务,如设置事务ID和回滚事务。dbms_session用于操作会话信息,如获取和修改会话状态。dbms_rowid...

    Oracle 9i数据库会话间通信的设计与实现.pdf

    实现会话间通信的一个关键步骤是编写PL/SQL语言的包装程序和存储过程,这些程序利用DBMS_PIPE包的功能。此外,可以通过OLE DB(Object Linking and Embedding for Database)执行存储过程,以在VC++等编程环境中实现...

    PLSQL中的多进程通信技术.doc

    DBMS_PIPE 是用于实现管道通信的工具,允许在连接到同一数据库的不同会话之间或存储过程与 Pro*C 应用程序之间传递信息。管道通信是一种简单、有效的数据传输方式。DBMS_PIPE 主要包括以下两个函数对: - pack_...

    spring-jms-oracle-aq.rar_oracle aq_spring oracle aq_spring oracl

    Oracle AQ支持多种协议和传输方式,如TCP/IP、JMS和DBMS_PIPE等。 在Spring框架中集成Oracle AQ,我们可以利用Spring的JMS模块。Spring JMS提供了一个抽象层,使得开发者可以方便地与各种JMS提供者进行交互,而无需...

    Oracle8i Supplied PL/SQL Packages Reference Release 2 (8.1.6)

    7. Oracle 存储过程:Oracle 存储过程是一种预编译的 SQL 语句,用于实现某些业务逻辑或数据操作。存储过程可以用于提高数据库性能、减少网络流量和实现数据安全等。 8. Oracle 函数:Oracle 函数是一种特殊的存储...

    在Oracle数据库中运行操作系统命令

    DBMS_PIPE是Oracle提供的一种进程间通信(IPC)机制,它允许不同的PL/SQL进程之间通过管道进行数据交换。虽然它的设计初衷不是为了执行操作系统命令,但通过巧妙地利用这一功能,我们可以在数据库内部触发外部的系统...

    ORACLE常用包参考手册

    7. **DBMS_METADATA**:用于获取和操作数据库的元数据,如表、索引、触发器、存储过程等对象的定义,常用于数据迁移或生成DDL脚本。 8. **DBMS_OUTPUT**:提供对数据库对象的统计信息,如表空间使用情况、索引性能...

    Expert One-on-One Oracle源代码

    UTL_HTTP允许在PL/SQL中进行HTTP请求,而DBMS_PIPE则涉及进程间通信,允许在数据库实例之间发送消息。 - **lobtofile.sql** 和 **page821.sql**:这些是SQL脚本文件,可能包含示例代码,演示如何操作LOB数据或执行...

    Oracle如何直接运行OS命令(上)第1/2页

    DBMS_PIPE是Oracle提供的一个包,它允许不同的进程之间通过管道进行通信。在操作系统层面,管道是一种用于进程间通信(IPC)的技术,而Oracle中的管道则提供了一种在数据库会话间传递信息的方式。虽然它们的概念相似...

    Oracle_韩顺平 PLSQL_韩顺平

    - **DBMS_PIPE:** 进程间通信。 - **DBMS_LOB:** 大对象类型(如BLOB/CLOB)的操作。 ### 总结 PL/SQL作为一种强大的过程化SQL语言,为Oracle数据库开发者提供了一个高度灵活、高效且可靠的编程环境。通过掌握...

    Oracle Database PL/SQL Packages and Types Reference 11g Release

    2. **内置PL/SQL包**:Oracle提供了一系列内置的PL/SQL包,如DBMS_OUTPUT用于调试输出,DBMS_ALERT用于异步通知,DBMS_PIPE用于进程间通信,DBMS_JOB和DBMS_SCHEDULER用于计划任务等。这些包极大地扩展了PL/SQL的...

    oracle分区详细管理

    `DBMS_PIPE`用于创建和管理管道,实现进程间的通信。这里将这两个包的执行权限授予了所有用户,以便于数据库的并发操作和通信。 4. **用户密码修改**: - 使用`ALTER USER`命令可以更改用户的口令,示例中将用户...

    Oracle SQLSERVER相互访问.docx

    - 在 Oracle 中创建外部表或使用 DBMS_PIPE、DBMS_SQL 等包来实现与 SQL Server 的交互。 总结起来,Oracle 和 SQL Server 之间的互访涉及到网络配置、数据库链接服务器的创建、RPC 设置以及跨数据库操作。确保...

    Oracle8i_PL_SQL高级程序设计

    10. **数据库链接**:PL/SQL支持远程数据库连接,通过DBMS_PIPE等包可以实现跨数据库的通信。 通过对《Oracle8i PL/SQL高级程序设计》的深入学习,读者不仅可以掌握PL/SQL编程的基本技巧,还能了解到如何利用这些...

    oracle中实现sepll,aspell函数

    在Oracle中实现`aspell`,可能需要通过一个外部程序接口(如DBMS_PIPE或DBMS_SCHEDULER)与系统上的`aspell`进程进行通信。 2. **数据预处理**: - 在实现`spell`和`aspell`之前,可能需要对文本数据进行预处理,...

    PLSQL高级编程

    DBMS_ALERT和DBMS_PIPE程序包提供了在数据库内部进行过程通信的机制。这部分内容可能涵盖如何使用报警和管道进行过程间通信,以及它们之间的比较。 11. PL/SQL和JAVA。Oracle数据库允许使用JAVA对象,这意味着...

    Oracle8i_9i数据库基础

    第一部分 Oracle SQL*PLUS基础 23 第一章 Oracle数据库基础 23 §1.1 理解关系数据库系统(RDBMS) 23 §1.1.1 关系模型 23 §1.1.2 Codd十二法则 24 §1.2 关系数据库系统(RDBMS)的组成 24 §1.2.1 RDBMS 内核 24...

Global site tag (gtag.js) - Google Analytics