应用程序开发人员的需求是这样的:
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批量处理提高效率
源代码:
- --1.生成可用代码池,重复执行过程为每一个国家生成一个可用代码池表,表名为org_code_加上两位国家代码
- CREATEORREPLACEPROCEDUREp_org_code
- IS
- BEGIN
- --tmp是一个提交后删除行的全局临时表
- FORiIN0..9999999
- LOOP
- INSERTINTOtmp
- VALUES(LPAD(i,7,'0'));
- ENDLOOP;
- INSERTINTOorg_code_00
- SELECT*
- FROMtmp
- ORDERBYDBMS_RANDOM.VALUE;
- COMMIT;
- END;
- --2.代码生成过程
- CREATEORREPLACEPROCEDUREp_gen_code(
- p_country_codeINVARCHAR2,--国家代码
- p_p1INVARCHAR2,--第一位规则字符串,如012345
- p_p2INVARCHAR2,--第二位规则字符串,如012345
- p_p3INVARCHAR2,--第三位规则字符串,如012345
- p_p4INVARCHAR2,--第四位规则字符串,如012345
- p_p5INVARCHAR2,--第五位规则字符串,如012345
- p_p6INVARCHAR2,--第六位规则字符串,如012345
- p_p7INVARCHAR2,--第七位规则字符串,如012345
- p_instrINVARCHAR2,--商品ID字符串,用,做分隔符
- p_countINNUMBERDEFAULT1000,--每次提交的个数
- r_outstrOUTVARCHAR2--输出需要生成的代码个数和实际生成的代码个数
- )
- IS
- l_idDBMS_SQL.varchar2_table;
- l_mcDBMS_SQL.varchar2_table;
- l_codeDBMS_SQL.varchar2_table;
- l_mc_strVARCHAR2(255);
- l_code_strVARCHAR2(7);
- l_id_countINT:=0;
- l_code_countINT:=0;
- l_idxINT;
- l_startINT:=1;
- l_substrVARCHAR2(32);
- l_instrVARCHAR2(2000);
- l_lengthINT;
- l_tablenameVARCHAR2(30):='org_code_'||p_country_code;
- l_sqlVARCHAR2(2000);
- l_countINT:=0;
- l_pointerINT:=0;
- l_real_countINT:=0;
- --IPC
- l_pipenameCONSTANTVARCHAR2(12):='mypipe';
- l_pipe_getcountCONSTANTVARCHAR2(12):='getcount';
- l_pipe_retcountCONSTANTVARCHAR2(12):='retcount';
- l_send_resultINT;
- BEGIN
- DBMS_PIPE.PURGE(l_pipename);
- IFp_instrISNULL
- THEN
- BEGIN
- SELECTID,mc
- BULKCOLLECTINTOl_id,l_mc
- FROMproduct;
- l_id_count:=l_id.COUNT;
- l_sql:=
- 'selectcode1from(selectcode1from'
- ||l_tablename
- ||'whereinstr('''
- ||p_p1
- ||''',substr(code1,1,1))>0andinstr('''
- ||p_p2
- ||''',substr(code1,2,1))>0andinstr('''
- ||p_p3
- ||''',substr(code1,3,1))>0andinstr('''
- ||p_p4
- ||''',substr(code1,4,1))>0andinstr('''
- ||p_p5
- ||''',substr(code1,5,1))>0andinstr('''
- ||p_p6
- ||''',substr(code1,6,1))>0andinstr('''
- ||p_p7
- ||''',substr(code1,7,1))>0whererownum<='
- ||l_id_count;
- EXECUTEIMMEDIATEl_sql
- BULKCOLLECTINTOl_code;
- l_code_count:=l_code.COUNT;
- WHILE(l_count<l_code_count)
- LOOP
- IFDBMS_PIPE.receive_message(l_pipename,0)=0
- THEN
- DBMS_PIPE.unpack_message(l_pipebuf);
- EXITWHENl_pipebuf='stop';
- ENDIF;
- IFDBMS_PIPE.receive_message(l_pipe_getcount,0)=0
- THEN
- DBMS_PIPE.PURGE(l_pipe_retcount);
- dbms_pipe_pack_message(TO_CHAR(l_count)||'|running');
- l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
- ENDIF;
- l_real_count:=
- LEAST(p_count,l_code_count-l_pointer*p_count);
- FORiIN1..l_real_count
- LOOP
- INSERTINTOproduct_code
- VALUES(l_code(l_pointer*p_count+i),
- l_mc(l_pointer*p_count+i),
- p_country_code);
- EXECUTEIMMEDIATE'deletefrom'
- ||l_tablename
- ||'wherecode1=:x'
- USINGl_code(l_pointer*p_count+i);
- UPDATEproduct
- SETstatus=1
- WHEREID=l_id(l_pointer*p_count+i);
- ENDLOOP;
- COMMIT;
- l_pointer:=pointer+1;
- l_count:=l_count+l_real_count;
- ENDLOOP;
- DBMS_PIPE.PURGE(l_pipe_retcount);
- DBMS_PIPE.pack_message(TO_CHAR(l_count)||'|end');
- l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
- r_outstr:=l_id_count||'|'||l_count;
- DBMS_OUTPUT.put_line(r_outstr);
- EXCEPTION
- WHENNO_DATA_FOUND
- THEN
- COMMIT;
- WHENOTHERS
- THEN
- RAISE;
- END;
- ELSE
- IFSUBSTR(p_instr,-1,1)=','
- THEN
- l_instr:=p_instr;
- ELSE
- l_instr:=p_instr||',';
- ENDIF;
- l_length:=LENGTH(l_instr);
- <<outer_loop>>
- WHILEl_start<l_length
- LOOP
- l_id_count:=l_id_count+1;
- l_idx:=INSTR(l_instr,',',l_start);
- l_substr:=SUBSTR(l_instr,l_start,l_idx-l_start);
- l_start:=l_idx+1;
- IFDBMS_PIPE.receive_message(l_pipename,0)=0
- THEN
- DBMS_PIPE.unpack_message(l_pipebuf);
- EXITWHENl_pipebuf='stop';
- ENDIF;
- IFDBMS_PIPE.receive_message(l_pipe_getcount,0)=0
- THEN
- DBMS_PIPE.PURGE(l_pipe_retcount);
- DBMS_PIPE.pack_message(l_code_count||'|running');
- l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
- ENDIF;
- BEGIN
- SELECTmc
- INTOl_mc_str
- FROMproduct
- WHEREID=l_substr;
- EXCEPTION
- WHENOTHERS
- THEN
- GOTOouter_loop;
- END;
- l_sql:=
- 'selectcode1from(selectcode1/*+first_rows*/from'
- ||l_tablename
- ||'whereinstr('''
- ||p_p1
- ||''',
- substr(code1,1,1))>0andinstr('''
- ||p_p2
- ||''',
- substr(code1,2,1))>0andinstr('''
- ||p_p3
- ||''',
- substr(code1,3,1))>0andinstr('''
- ||p_p4
- ||''',
- substr(code1,4,1))>0andinstr('''
- ||p_p5
- ||''',
- substr(code1,5,1))>0andinstr('''
- ||p_p6
- ||''',
- substr(code1,6,1))>0andinstr('''
- ||p_p7
- ||''',
- substr(code1,1,1))>0)whererownum=1';
- BEGIN
- EXECUTEIMMEDIATEl_sql
- INTOl_code_str;
- EXCEPTION
- WHENNO_DATA_FOUND
- THEN
- EXIT;
- END;
- IFSQL%ROWCOUNT=1
- THEN
- l_code_count:=l_code_count+1;
- ENDIF;
- INSERTINTOproduct_code
- VALUES(l_code_str,l_wzmc_str,p_country_code);
- EXECUTEIMMEDIATE'deletefrom'||l_tablename||'wherecode1=:x'
- USINGl_code_str;
- UPDATEproduct
- SETstatus=1
- WHEREID=l_substr;
- ENDLOOP;
- COMMIT;
- DBMS_PIPE.PURGE(l_pipe_retcount);
- DBMS_PIPE.pack_message(TO_CHAR(l_code_count)||'|end');
- l_send_result:=DBMS_PIPE.send_message(l_pipe_retcount);
- r_outstr:=
- LENGTH(l_instr)
- -LENGTH(REPLACE(l_instr,',',''))
- ||'|'
- ||l_code_count;
- DBMS_OUTPUT.put_line(r_outstr);
- ENDIF;
- ENDp_gen_code;
- --3.终止过程
- CREATEORREPLACEPROCEDUREp_stop
- IS
- l_pipenameVARCHAR2(12):='mypipe';
- l_create_resultINTEGER:=DBMS_PIPE.create_pipe(l_pipename);
- l_send_resultINTEGER;
- BEGIN
- DBMS_PIPE.PURGE(l_pipename);
- DBMS_PIPE.pack_message('stop');
- l_send_result:=DBMS_PIPE.send_message(l_pipename);
- DBMS_OUTPUT.put_line('l_send_result:'||l_send_result);
- ENDp_stop;
- --4.取得当前已经生成代码的个数
- CREATEORREPLACEFUNCTIONfn_getcount(p_timeoutNUMBER)
- RETURNVARCHAR2
- IS
- l_pipebufVARCHAR2(20);
- l_pipe_getcountVARCHAR2(12):='getcount';
- l_pipe_retcountVARCHAR2(12):='retcount';
- l_statusNUMBER;
- l_receiveNUMBER;
- BEGIN
- DBMS_PIPE.PURGE(l_pipe_getcount);
- DBMS_PIPE.pack_message(l_pipe_getcount);
- l_status:=DBMS_PIPE.send_message(l_pipe_getcount);
- l_receive:=
- DBMS_PIPE.receive_message(l_pipe_retcount,NVL(p_timeout,0));
- IFl_receive=0
- THEN
- DBMS_PIPE.unpack_message(l_pipebuf);
- RETURNTO_CHAR(l_pipebuf);
- ELSE
- RETURNTO_CHAR('Timedout!');
- ENDIF;
- ENDfn_getcount;
分享到:
相关推荐
dbms_pipe包提供了管道通信机制,允许进程间传递数据。dbms_alert则用于发布和接收异步通知。dbms_transaction管理事务,如设置事务ID和回滚事务。dbms_session用于操作会话信息,如获取和修改会话状态。dbms_rowid...
实现会话间通信的一个关键步骤是编写PL/SQL语言的包装程序和存储过程,这些程序利用DBMS_PIPE包的功能。此外,可以通过OLE DB(Object Linking and Embedding for Database)执行存储过程,以在VC++等编程环境中实现...
DBMS_PIPE 是用于实现管道通信的工具,允许在连接到同一数据库的不同会话之间或存储过程与 Pro*C 应用程序之间传递信息。管道通信是一种简单、有效的数据传输方式。DBMS_PIPE 主要包括以下两个函数对: - pack_...
Oracle AQ支持多种协议和传输方式,如TCP/IP、JMS和DBMS_PIPE等。 在Spring框架中集成Oracle AQ,我们可以利用Spring的JMS模块。Spring JMS提供了一个抽象层,使得开发者可以方便地与各种JMS提供者进行交互,而无需...
7. Oracle 存储过程:Oracle 存储过程是一种预编译的 SQL 语句,用于实现某些业务逻辑或数据操作。存储过程可以用于提高数据库性能、减少网络流量和实现数据安全等。 8. Oracle 函数:Oracle 函数是一种特殊的存储...
DBMS_PIPE是Oracle提供的一种进程间通信(IPC)机制,它允许不同的PL/SQL进程之间通过管道进行数据交换。虽然它的设计初衷不是为了执行操作系统命令,但通过巧妙地利用这一功能,我们可以在数据库内部触发外部的系统...
7. **DBMS_METADATA**:用于获取和操作数据库的元数据,如表、索引、触发器、存储过程等对象的定义,常用于数据迁移或生成DDL脚本。 8. **DBMS_OUTPUT**:提供对数据库对象的统计信息,如表空间使用情况、索引性能...
UTL_HTTP允许在PL/SQL中进行HTTP请求,而DBMS_PIPE则涉及进程间通信,允许在数据库实例之间发送消息。 - **lobtofile.sql** 和 **page821.sql**:这些是SQL脚本文件,可能包含示例代码,演示如何操作LOB数据或执行...
DBMS_PIPE是Oracle提供的一个包,它允许不同的进程之间通过管道进行通信。在操作系统层面,管道是一种用于进程间通信(IPC)的技术,而Oracle中的管道则提供了一种在数据库会话间传递信息的方式。虽然它们的概念相似...
- **DBMS_PIPE:** 进程间通信。 - **DBMS_LOB:** 大对象类型(如BLOB/CLOB)的操作。 ### 总结 PL/SQL作为一种强大的过程化SQL语言,为Oracle数据库开发者提供了一个高度灵活、高效且可靠的编程环境。通过掌握...
2. **内置PL/SQL包**:Oracle提供了一系列内置的PL/SQL包,如DBMS_OUTPUT用于调试输出,DBMS_ALERT用于异步通知,DBMS_PIPE用于进程间通信,DBMS_JOB和DBMS_SCHEDULER用于计划任务等。这些包极大地扩展了PL/SQL的...
`DBMS_PIPE`用于创建和管理管道,实现进程间的通信。这里将这两个包的执行权限授予了所有用户,以便于数据库的并发操作和通信。 4. **用户密码修改**: - 使用`ALTER USER`命令可以更改用户的口令,示例中将用户...
- 在 Oracle 中创建外部表或使用 DBMS_PIPE、DBMS_SQL 等包来实现与 SQL Server 的交互。 总结起来,Oracle 和 SQL Server 之间的互访涉及到网络配置、数据库链接服务器的创建、RPC 设置以及跨数据库操作。确保...
10. **数据库链接**:PL/SQL支持远程数据库连接,通过DBMS_PIPE等包可以实现跨数据库的通信。 通过对《Oracle8i PL/SQL高级程序设计》的深入学习,读者不仅可以掌握PL/SQL编程的基本技巧,还能了解到如何利用这些...
在Oracle中实现`aspell`,可能需要通过一个外部程序接口(如DBMS_PIPE或DBMS_SCHEDULER)与系统上的`aspell`进程进行通信。 2. **数据预处理**: - 在实现`spell`和`aspell`之前,可能需要对文本数据进行预处理,...
DBMS_ALERT和DBMS_PIPE程序包提供了在数据库内部进行过程通信的机制。这部分内容可能涵盖如何使用报警和管道进行过程间通信,以及它们之间的比较。 11. PL/SQL和JAVA。Oracle数据库允许使用JAVA对象,这意味着...
第一部分 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...