|
常用链接
留言簿
随笔档案
搜索
最新评论
阅读排行榜
评论排行榜
Powered by: 博客园
模板提供:沪江博客
|
|
|
|
|
发新文章 |
|
|
2012年9月21日
我能抽象出整个世界.. . 但是我却不能抽象出你... 你肯定是一个单例,因为你是那样的独一无二... 所以我的世界并不完整... 我可以重载甚至覆盖这个世界里的任何一种方法... 但是却不能覆盖对你的思念... 也许命中注定了 你与我存在于不同的包里... 在你的世界里,你被烙上了私有的属性... 我用尽全身力气,也找不到访问你的接口... 我不愿就此甘心,找到了藏身在javaeye神殿的巫师,教会了我穿越时空的方法... 终于,我用反射这把利剑,打开了你空间的缺口... 并发现了接近你的秘密... 当我迫不及待地调用了爱你这个方法... 并义无返顾的把自己作为参数传进这个方法时... 我才发现爱上你是一个没有终止条件的递归... 它不停的返回我对你的思念并压入我心里的堆栈... 在这无尽的黑夜中 , tb终于体验到你对我爱的回调... 我的内存里已经再也装不下别人... 当我以为将与你在这个死循环中天荒地老时... 万恶的系统抛出了爱的异常... 此刻我才发现,我不过是操纵于虚拟机下的一个线程,你也是... 但我毫不后悔,因为在爱的洗礼之后... 我看见了一个新的生命,那是我们的, 继承
线程是Java语言的一个部分,而且是Java的最强大的功能之一。究竟什么是线程,为什么要开发基于线程的应用程序?在本文中,我们将深入了解一下线程的用法,以及使用线程的一些技术。在我们开始讲述线程之前,最好先了解一下有关背景知识和分析一下线程的工作原理。
当程序员一开始开发应用程序时,这些应用程序只能在一个时间内完成一件事情。应用程序从主程序开始执行,直到运行结束,像 Fortran/Cobol/Basic这些语言均是如此。
随着时间的推移,计算机发展到可以在同一时间段内运行不止一个应用程序的时代了,但是应用程序运行时仍然是串行的,即从开始运行到结束,下一条指令接着上一条指令执行。到最近,程序发展到可以在执行时,以若干个线程的形式运行。Java就具有运行多线程的能力,可以在同一时间段内进行几个操作,这就意味着给定的操作不必等到另外一个操作结束之后,才能开始。而且对某个操作可以指定更高一级的优先级。
不少程序语言,包括ADA, Modula-2和C/C++,已经可以提供对线程的支持。同这些语言相比,Java的特点是从最底层开始就对线程提供支持。除此以外,标准的Java类是可重入的,允许在一个给定的应用程序中由多个线程调用同一方法,tb而线程彼此之间又互不干扰。Java的这些特点为多线程应用程序的设计奠定了基础。
什么是线程?
究竟什么是线程呢?正如在图A中所示,一个线程是给定的指令的序列 (你所编写的代码),一个栈(在给定的方法中定义的变量),以及一些共享数据(类一级的变量)。线程也可以从全局类中访问静态数据。
#g_kclist{font-size:12px;width:570px;float:none; margin-top:5px; clear:right}
#g_kclist a{color:#000; text-decoration:none}
#g_kclist h2{margin:0px;padding:0px;font-size:14px; text-align:center;background:url(http://www.thea.cn/zt/zt_img/zczhongduan.gif) no-repeat;line-height:31px;color:#fff}
#g_kclist table{line-height:25px;background:#B0DA90;margin-top:8px}
#g_kclist table td{ text-align:center;background:#fff}
#g_kclist table td.td1 a{color:#f00}
#g_kclist table th{background:#F2F7ED;color:#525F46}
有多种方法的,我只说两种最简单的。 一、定义数据源sql时,定义一个变量:xb,然后数据源写成: select * from [运动员表] where [性别]=:xb 再从窗口的open事件中写: dw_1.settransobject(sqlca) dw_1.retrieve('男')//把变量传给数据窗口,只刷出男生。 即可实现。 二、定义数据源sql时,直接写成: select * from [运动员表] 窗口的open事件中写: dw_1.settransobejct(sqlca) dw_1.retrieve()//这句是刷新出所有的运动员,包括男女 dw_1.setfilter("[性别]='男'")//为数据窗口设置过滤 dw_1.filter()//使用过滤字符串过滤数据 也可以实现你所要求的。 是不是数据窗口的行高不够(这个会挡住每行数据的一点点), 还有可能是details的band tb向下拖拖 多放点空间 (这个肯能挡住最下面的数据)
找到了问题产生的原因后,下面来讨论如何解决该问题。对于Oracle Enterprise Manager中的所有工具,有一个配置文件名为dbappscfg.properties,修改该文件即可解决上述问题。这个文件的位置在$ORACLE_HOME\sysman\config目录下,用任何的文本编辑器打开该文件,在这个文件里面,找到这样一项,
# SQLPLUS_NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
去掉注释符#,同时将其修改为
SQLPLUS_NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
对于Windows操作系统,还需要修改一项,在文件中找到# SQLPLUS_SYSTEMROOT=c:\\WINNT40,去掉注释符,将其修改为你所在机器的操作系统主目录。如操作系统的主目录在D盘的Winnt下,则将其修改为
SQLPLUS_SYSTEMROOT=d:\\WINNT。
对于后面一项的修改只对Windows操作系统进行,对UNIX操作系统则不需要。如果在Windows操作系统中不修改该项,在Oracle Enterprise Manager中,连接系统时,会提示如下的错误:
ORA-12560 TNS:protocol adapter error
或者
ORA-12545 Connect failed because target host or objectb does not exist
修改完成后,保存文件,退出编辑。重新连接SQL PLUS Worksheet,字符集乱码问题得到解决,显示正确的简体中文字符集。
.item-area{width:578px;margin:15px auto;border-top:1px solid #ddd;color:#666}
.item-area a,.item-area a:link,.item-area a:visited{color:#666;text-decoration:none}
.item-area a:hover{color:#3a7ad9;text-decoration:underline;}
a img{border:none;vertical-align:middle}
.item-area h2,.item-area h3{float:none;font-size:100%;font-weight:normal;}
.item-area .h2{height:25px;margin:10px 0;padding-left:35px;*float:left;font:bold 14px/25px "宋体";background:url(http://sns.thea.cn/module/images/icos.png) no-repeat 0 0}
.item-area span.more{float:right;font:normal 12px/25px "宋体"}
.item-area a.more{float:right;font:normal 12px/25px "宋体"}
.item-a{margin-bottom:15px}
.item-a .h-ksrm{background-position:0 0}
.item-a li{*display:inline;overflow:hidden;zoom:1;line-height:2em;padding-left:35px;font-size:14px;background: url(http://sns.thea.cn/module/images/btns.png) no-repeat -1px -28px;}
.item-a li a{float:left;}
.item-a .testBtn{float:right;width:58px;height:21px;line-height:21px;font-size:12px;margin-top:5px;margin-top:3px;text-align:center;background:url(http://sns.thea.cn/module/images/btns.png) no-repeat -1px -1px; color:#FFFFFF;}
.item-a a.freeBtn{width:20px;margin:0 0 0 6px;line-height:28px;color:#fff;font-size:12px;text-indent:-9999px;background: url(http://sns.thea.cn/module/images/icos.png) no-repeat 0 -131px;}
.item-a li.hots a.freeBtn{background-position:0 -105px}
.item-a a.examnum em{font-style:normal;color:red;font-weight:bold;}
.item-b {padding:5px 0 20px;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd}
.xsjl-list-col3s li{display:table-cell;*display:inline;zoom:1;vertical-align:top;width:182px;padding-right:10px;line-height:150%;font-size:12px;}
.item-b .h-xsjl{background-position:0 -26px}
.item-b .pic{float:left;margin:3px 10px 0 0;}
.item-b em{font-style:normal;color:#dc2c2c}
.item-b a.join{display:inline-block;padding-left:20px;background:url(http://sns.thea.cn/module/images/icos.png) no-repeat 0 -160px}
.item-b .xsjl-list-col3s h3 a{display:inline-block;width:120px;overflow:hidden;white-space:nowrap;color:#3a7ad9}
.item-b .xsjl-list-col3s h3{text-align:left;line-height:150%;font-family:"宋体","微软雅黑"}
我的myoracle.txt脚本内容如下:
drop procedure PRO_RECEIPTSTOCK_5D19A;
create or replace procedure PRO_RECEIPTSTOCK_5D19A IS
v_STOCKID NUMBER(13);
v_STARTNO VARCHAR2(10);
v_ENDNO VARCHAR2(10);
v_RECEIPTTYPE NUMBER(13);
v_STATUS CHAR(1);
v_COUNT NUMBER(13);
v_UNITID NUMBER(13);
V_RELATEUSERNAME VARCHAR2(150);
V_GLIDENUM NUMBER(20);
V_FLAG VARCHAR2(2);
V_PROCTM DATE;
V_SPROCTM VARCHAR2(30);
V_REGISTERTM DATE;
V_SREGISTERTM VARCHAR2(30);
V_DBUSER VARCHAR2(20);
V_CURSQL VARCHAR2(4000);
V_MYCOUNT NUMBER;
CURSOR C_RECEIPTSTOCK_TMP IS
SELECT
STOCKID,
STARTNO,
ENDNO,
RECEIPTTYPE,
STATUS,
COUNT,
UNITID,
RELATEUSERNAME,
GLIDENUM,
FLAG,
PROCTM,
REGISTERTM,
DBUSER
FROM GFMIS_ALL.RECEIPTSTOCK_5D19A_TMP
WHERE
ZTOF_STATUS = '1'
AND DBUSER IS NOT NULL;
begin
--把票据类型为5D的缴款书在库存中更新成一般缴款书
UPDATE GFMIS_ALL.RECEIPTSTOCK T SET T.RECEIPTTYPE=4765 WHERE EXISTS (SELECT 1 FROM GFMIS_ALL.RECEIPTSTOCK_5D19A_TMP TT WHERE TT.STOCKID = substr(T.STOCKID, 4, length(TRIM(T.STOCKID))) AND TT.ZTOF_STATUS = '1' AND TT.RECEIPTTYPE=11533);
OPEN C_RECEIPTSTOCK_TMP;
LOOP
FETCH C_RECEIPTSTOCK_TMP INTO v_STOCKID,
v_STARTNO,
v_ENDNO,
v_RECEIPTTYPE,
v_STATUS,
v_COUNT,
v_UNITID,
V_RELATEUSERNAME,
V_GLIDENUM,
V_FLAG,
V_PROCTM,
V_REGISTERTM,
V_DBUSER;
EXIT WHEN C_RECEIPTSTOCK_TMP%NOTFOUND;
V_CURSQL := 'SELECT COUNT(1) FROM ' || V_DBUSER || '.RECEIPTSTOCK WHERE STOCKID = ' || v_STOCKID;
EXECUTE IMMEDIATE V_CURSQL INTO V_MYCOUNT;
IF (V_MYCOUNT = 0) THEN
V_SPROCTM :=TO_CHAR(V_PROCTM,'YYYY-MM-DD HH24:MI:SS');
V_SREGISTERTM :=TO_CHAR(V_REGISTERTM,'YYYY-MM-DD HH24:MI:SS');
IF (v_RECEIPTTYPE = 11533) THEN
v_RECEIPTTYPE := 4765;
END IF;
V_CURSQL :='INSERT INTO ' || V_DBUSER || '.RECEIPTSTOCK (STOCKID,STARTNO,ENDNO,RECEIPTTYPE,STATUS,COUNT,UNITID,RELATEUSERNAME,GLIDENUM,FLAG,PROCTM,REGISTERTM) VALUES (' || v_STOCKID || ',''' || v_STARTNO || ''',''' || v_ENDNO || ''',' || v_RECEIPTTYPE || ',''' || v_STATUS || ''',' || v_COUNT || ',' || 1 || ',''' || V_RELATEUSERNAME || ''',' || NVL(V_GLIDENUM, 0) || ',''' || V_FLAG || ''', TO_DATE(''' || V_SPROCTM || ''',''YYYY-MM-DD HH24:MI:SS''), TO_DATE(''' || V_SREGISTERTM || ''',''YYYY-MM-DD HH24:MI:SS''))';
EXECUTE IMMEDIATE V_CURSQL;
UPDATE GFMIS_ALL.RECEIPTSTOCK_5D19A_TMP T SET T.ZTOF_STATUS = '0' WHERE T.STOCKID = v_STOCKID AND T.ZTOF_STATUS = '1';
DELETE FROM GFMIS.RECEIPTSTOCK WHERE STOCKID = v_STOCKID;
END IF;
END LOOP;
UPDATE GFMIS_ALL.RECEIPTSTOCK_5D19A_TMP T SET T.ZTOF_STATUS = '0' WHERE T.ZTOF_STATUS = '1' AND T.RECEIPTTYPE=11533;
COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
CLOSE C_RECEIPTSTOCK_TMP;
dbms_output.put_line(SQLERRM);
IF C_RECEIPTSTOCK_TMP%ISOPEN THEN
CLOSE C_RECEIPTSTOCK_TMP;
END IF;
RAISE;
end PRO_RECEIPTSTOCK_5D19A;
/
DROP TRIGGER TRI_RECEIPTSTOCK_CHG_AFT;
CREATE OR REPLACE TRIGGER TRI_RECEIPTSTOCK_CHG_AFT
AFTER DELETE OR INSERT OR UPDATE
ON RECEIPTSTOCK
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
curTable varchar2(50);
curType char(1);
curTime TimeStamp;
id number(13);
curID number(13);
curSQL varchar2(4000);
curUser varchar2(30);
v_distno varchar2(30);
v_dbuser varchar2(30);
v_mycount number(13);
BEGIN
IF (INSERTING) THEN
--把票据类型为5DTB的缴款书在库存中更新成一般缴款书 或者 把指定的19个单位的库存移到分库里面
SELECT COUNT(1) INTO v_mycount FROM GFMIS_ALL.RECEIPTSTOCK_DISTRICT T WHERE T.UNITID = :NEW.UNITID;
IF (v_mycount > 0) THEN
SELECT T.DBUSER INTO v_dbuser FROM GFMIS_ALL.RECEIPTSTOCK_DISTRICT T WHERE T.UNITID = :NEW.UNITID;
curSQL := 'SELECT COUNT(1) FROM ' || v_dbuser || '.RECEIPTSTOCK WHERE UNITID = ' || substr(:NEW.UNITID, 4, length(TRIM(:NEW.UNITID))) || ' AND RECEIPTTYPE = ' || :NEW.RECEIPTTYPE || ' AND STARTNO <= ''' || :NEW.STARTNO || ''' AND ENDNO >= ''' || :NEW.ENDNO || '';
EXECUTE IMMEDIATE curSQL INTO v_mycount;
if (v_mycount = 0) then
INSERT INTO GFMIS_ALL.RECEIPTSTOCK_5D19A_TMP (STOCKID,STARTNO,ENDNO,RECEIPTTYPE,STATUS,COUNT,UNITID,RELATEUSERNAME,GLIDENUM,FLAG,PROCTM,REGISTERTM,DBUSER,ZTOF_STATUS) VALUES (substr(:NEW.STOCKID, 4, length(TRIM(:NEW.STOCKID))),:NEW.STARTNO,:NEW.ENDNO,:NEW.RECEIPTTYPE,:NEW.STATUS,:NEW.COUNT,substr(:NEW.UNITID, 4, length(TRIM(:NEW.UNITID))),:NEW.RELATEUSERNAME,:NEW.GLIDENUM,:NEW.FLAG,:NEW.PROCTM,:NEW.REGISTERTM,v_dbuser,'1');
end if;
END IF;
IF (:NEW.RECEIPTTYPE = 11533) THEN
INSERT INTO GFMIS_ALL.RECEIPTSTOCK_5D19A_TMP (STOCKID,STARTNO,ENDNO,RECEIPTTYPE,STATUS,COUNT,UNITID,RELATEUSERNAME,GLIDENUM,FLAG,PROCTM,REGISTERTM,DBUSER,ZTOF_STATUS) VALUES (substr(:NEW.STOCKID, 4, length(TRIM(:NEW.STOCKID))),:NEW.STARTNO,:NEW.ENDNO,:NEW.RECEIPTTYPE,:NEW.STATUS,:NEW.COUNT,substr(:NEW.UNITID, 4, length(TRIM(:NEW.UNITID))),:NEW.RELATEUSERNAME,:NEW.GLIDENUM,:NEW.FLAG,:NEW.PROCTM,:NEW.REGISTERTM,NULL,'1');
END IF;
END IF;
select seq_exchange_temp.nextval into id from dual;
curUser :=lower(SYS_CONTEXT('userenv', 'session_user'));
if (curUser != 'all_exchange_user') then
SELECT CURRENT_TIMESTAMP INTO curTime FROM DUAL;
curTable := 'RECEIPTSTOCK';
if (deleting) then
v_distno:=substr(:OLD.STOCKID,2,2);
select dbuser into v_dbuser from GFMIS_ALL.DISTRICT where distno=v_distno;
curType := '3';
curID := :OLD.stockid;
if (curUser = 'gfmis_all') then
curSQL := 'SP_EX_RECEIPTSTOCK_DEL(''' || :OLD.STOCKID || ''')';
else
curSQL := 'SP_EX_RECEIPTSTOCK_DEL(''' || substr(:OLD.STOCKID,4) || ''')';
end if;
end if;
if (updating) then
v_distno:=substr(:OLD.STOCKID,2,2);
select dbuser into v_dbuser from GFMIS_ALL.DISTRICT where distno=v_distno;
curType := '2';
curID := :OLD.stockid;
if (curUser = 'gfmis_all') then
curSQL := 'SP_EX_RECEIPTSTOCK_UPD(''' || :OLD.STOCKID || ''', ''' || :NEW.COUNT || ''', ''' || FN_FMT_SQL(:NEW.ENDNO) || ''', ''' || FN_FMT_SQL(:NEW.FLAG) || ''', ''' || :NEW.GLIDENUM || ''', ''' || TO_CHAR(:NEW.PROCTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || :NEW.RECEIPTTYPE || ''', ''' || TO_CHAR(:NEW.REGISTERTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || FN_FMT_SQL(:NEW.RELATEUSERNAME) || ''', ''' || FN_FMT_SQL(:NEW.STARTNO) || ''', ''' || FN_FMT_SQL(:NEW.STATUS) || ''', ''' || :NEW.STOCKID || ''', ''' || :NEW.UNITID || ''')';
else
curSQL := 'SP_EX_RECEIPTSTOCK_UPD(''' || substr(:OLD.STOCKID,4) || ''', ''' || :NEW.COUNT || ''', ''' || FN_FMT_SQL(:NEW.ENDNO) || ''', ''' || FN_FMT_SQL(:NEW.FLAG) || ''', ''' || :NEW.GLIDENUM || ''', ''' || TO_CHAR(:NEW.PROCTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || :NEW.RECEIPTTYPE || ''', ''' || TO_CHAR(:NEW.REGISTERTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || FN_FMT_SQL(:NEW.RELATEUSERNAME) || ''', ''' || FN_FMT_SQL(:NEW.STARTNO) || ''', ''' || FN_FMT_SQL(:NEW.STATUS) || ''', ''' || substr(:NEW.STOCKID ,4) || ''', ''' || substr(:NEW.UNITID ,4) || ''')';
end if;
end if;
if (inserting) then
v_distno:=substr(:NEW.STOCKID,2,2);
select dbuser into v_dbuser from GFMIS_ALL.DISTRICT where distno=v_distno;
curType := '1';
curID := :NEW.stockid;
if (curUser = 'gfmis_all') then
curSQL := 'SP_EX_RECEIPTSTOCK_INS(''' || :NEW.COUNT || ''', ''' || FN_FMT_SQL(:NEW.ENDNO) || ''', ''' || FN_FMT_SQL(:NEW.FLAG) || ''', ''' || :NEW.GLIDENUM || ''', ''' || TO_CHAR(:NEW.PROCTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || :NEW.RECEIPTTYPE || ''', ''' || TO_CHAR(:NEW.REGISTERTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || FN_FMT_SQL(:NEW.RELATEUSERNAME) || ''', ''' || FN_FMT_SQL(:NEW.STARTNO) || ''', ''' || FN_FMT_SQL(:NEW.STATUS) || ''', ''' || :NEW.STOCKID || ''', ''' || :NEW.UNITID || ''')';
else
curSQL := 'SP_EX_RECEIPTSTOCK_INS(''' || :NEW.COUNT || ''', ''' || FN_FMT_SQL(:NEW.ENDNO) || ''', ''' || FN_FMT_SQL(:NEW.FLAG) || ''', ''' || :NEW.GLIDENUM || ''', ''' || TO_CHAR(:NEW.PROCTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || :NEW.RECEIPTTYPE || ''', ''' || TO_CHAR(:NEW.REGISTERTM,'YYYY-MM-DD HH24:MI:SS') || ''', ''' || FN_FMT_SQL(:NEW.RELATEUSERNAME) || ''', ''' || FN_FMT_SQL(:NEW.STARTNO) || ''', ''' || FN_FMT_SQL(:NEW.STATUS) || ''', ''' || substr(:NEW.STOCKID ,4) || ''', ''' || substr(:NEW.UNITID ,4) || ''')';
end if;
end if;
if (curUser = 'gfmis_all') then
INSERT INTO exchange_temp (ID,SEQID, TABLENAME, GENSQL, TYPE, DT, STATUS,ZKSTATUS,DBUSER)
VALUES (id, curID,curTable, curSQL, curType, curTime, '2','1',v_dbuser );
else
INSERT INTO exchange_temp (ID,SEQID, TABLENAME, GENSQL, TYPE, DT, STATUS,ZKSTATUS,DBUSER)
VALUES (id, curID,curTable, curSQL, curType, curTime, '2','0',v_dbuser );
end if;
end if;
EXCEPTION
WHEN OTHERS THEN
RAISE;
end TRI_RECEIPTSTOCK_CHG_AFT;
/
commit;
【注】:在每一个DROP语句后面不能加/,而在创建PROCEDURE和TRIGGER的之后必须加/符号,否则下面的脚本会
执行失败的。
执行txt和sql的脚本写法如下:
SQL> @D:\myoracle.txt;
Procedure dropped
Procedure created
Trigger dropped
Trigger created
Commit complete
SQL>
exec后面执行跟存储过程名或函数名[exec只能在命令行执行,call可以在任何环境下执行]。
1.dbms_random.value方法
dbms_random是一个可以生成随机数值或者字符串的程序包。这个包有initialize()、seed()、terminate()、value()、normal()、random()、string()等几个函数,但value()是最常用的,value()的用法一般有两个种,第一 function value return number; 这种用法没有参数,会返回一个具有38位精度的数值,范围从0.0到1.0,但不包括1.0,如下示例: SQL> set serverout on SQL> begin 2 for i in 1..10 loop 3 dbms_output.put_line(round(dbms_random.value*100)); 4 end loop; 5 end; 6 / 46 19 45 37 33 57 61 20 82 8 PL/SQL 过程已成功完成。 SQL> 第二种value带有两个参数,第一个指下限,第二个指上限,将会生成下限到上限之间的数字,但不包含上限,“学无止境”兄说的就是第二种,如下: SQL> begin 2 for i in 1..10 loop 3 dbms_output.put_line(trunc(dbms_random.value(1,101))); 4 end loop; 5 end; 6 / 97 77 13 86 68 16 55 36 54 46 PL/SQL 过程已成功完成。
2. dbms_random.string 方法
某些用户管理程序可能需要为用户创建随机的密码。使用10G下的dbms_random.string 可以实现这样的功能。
例如:
SQL> select dbms_random.string('P',8 ) from dual ;
DBMS_RANDOM.STRING('P',8)
--------------------------------------------------------------------------------
3q<M"yf[
第一个参数的含义:
■ 'u', 'U' - returning string in uppercase alpha characters
■ 'l', 'L' - returning string in lowercase alpha characters
■ 'a', 'A' - returning string in mixed case alpha characters
■ 'x', 'X' - returning string in uppercase alpha-numeric
characters
■ 'p', 'P' - returning string in any printable characters.
Otherwise the returning string is in uppercase alpha
characters.
P 表示 printable,即字符串由任意可打印字符构成
而第二个参数表示返回的字符串长度。
3. dbms_random.random 方法
random返回的是BINARY_INTEGER类型值,产生一个任意大小的随机数
与dbms_random.value 的区别举例:
Order By dbms_random.value; 这条语句功能是实现记录的随机排序 另外: dbms_random.value 和 dbms_random.random 两者之间有什么区别? 1。Order By dbms_random.value ,为结果集的每一行计算一个随机数,dbms_random.value 是结果集的一个列(虽然这个列并不在select list 中),然后根据该列排序,得到的顺序自然就是随机的啦。 2。看看desc信息便知道vlue和random这两个函数的区别了,value返回的是number类型,tb并且返回的值介于1和0之间,而random返回的是BINARY_INTEGER类型(以二进制形式存储的数字,据说运算的效率高于number但我没测试过,但取值范围肯定小于number,具体限制得查资料了) 如果你要实现随机排序,还是用value函数吧
4. dbms_random.normal方法
NORMAL函数返回服从正态分布的一组数。此正态分布标准偏差为1,期望值为0。这个函数返回的数值中有68%是介于-1与+1之间,95%介于-2与+2之间,99%介于-3与+3之间。
5. dbms_random.send方法
用于生成一个随机数种子,设置种子的目的是可以重复生成随机数,用于调试。否则每次不同,难以调度。
对于一般的select操作,如果使用动态的sql语句则需要进行以下几个步骤:
open cursor---> parse---> define column---> excute---> fetch rows---> close cursor;
而对于dml操作(insert,update)则需要进行以下几个步骤:
open cursor---> parse---> bind variable---> execute---> close cursor;
对于delete操作只需要进行以下几个步骤:
open cursor---> parse---> execute---> close cursor;
例一:
create table test(n_id number, v_name varchar2(50), d_insert_date date);
alter table test add constraint pk_id primary key(n_id);
declare
v_cursor number;
v_sql varchar2(200);
v_id number;
v_name varchar2(50);
v_date date;
v_stat number;
begin
v_id := 1;
v_name := '测试 insert';
v_date := sysdate;
v_cursor := dbms_sql.open_cursor; --打开游标
v_sql := 'insert into test(n_id, v_name, d_insert_date) values(:v_id,:v_name,:v_date)';
dbms_sql.parse(v_cursor, v_sql, dbms_sql.native); --解析SQL
dbms_sql.bind_variable(v_cursor, ':v_id', v_id); --绑定变量
dbms_sql.bind_variable(v_cursor, ':v_name', v_name);
dbms_sql.bind_variable(v_cursor, ':v_date', v_date);
v_stat := dbms_sql.execute(v_cursor); --执行
dbms_sql.close_cursor(v_cursor); --关闭游标
commit;
end;
例二:
declare
v_cursor number;
v_sql varchar2(200);
v_id number;
v_name varchar2(50);
v_stat number;
begin
v_name := '测试 update';
v_id := 1;
v_cursor := dbms_sql.open_cursor;
v_sql := 'update test set v_name = :v_name, d_insert_date = :v_date where n_id = :v_id';
dbms_sql.parse(v_cursor, v_sql, dbms_sql.native);
dbms_sql.bind_variable(v_cursor, ':v_name', v_name);
dbms_sql.bind_variable(v_cursor, ':v_date', sysdate);
dbms_sql.bind_variable(v_cursor, ':v_id', v_id);
v_stat := dbms_sql.execute(v_cursor);
dbms_sql.close_cursor(v_cursor);
commit;
end;
例三:
declare
v_cursor number;
v_sql varchar2(200);
v_id number;
v_stat number;
begin
v_id := 1;
v_sql := 'delete from test where n_id = :v_id';
v_cursor := dbms_sql.open_cursor;
dbms_sql.parse(v_cursor, v_sql, dbms_sql.native);
dbms_sql.bind_variable(v_cursor, ':v_id', v_id);
v_stat := dbms_sql.execute(v_cursor);
dbms_sql.close_cursor(v_cursor);
commit;
end;
例四:
declare
v_cursor number;
v_sql varchar2(200);
v_id number;
v_name varchar2(50);
v_date varchar2(10);
v_stat number;
begin
v_sql := 'select n_id, v_name, to_char(d_insert_date, ''yyyy-mm-dd'') from test';
v_cursor := dbms_sql.open_cursor; --打开游标
dbms_sql.parse(v_cursor, v_sql, dbms_sql.native); --解析游标
dbms_sql.define_column(v_cursor, 1, v_id); --定义列
dbms_sql.define_column(v_cursor, 2, v_name, 50); --注意:当变量为varchar2类型时,要加长度
dbms_sql.define_column(v_cursor, 3, v_date, 10);
v_stat := dbms_sql.execute(v_cursor); --执行SQL
loop
exit when dbms_sql.fetch_rows(v_cursor) <= 0; --fetch_rows在结果集中移动游标,如果未抵达末尾,返回1。
dbms_sql.column_value(v_cursor, 1, v_id); --将当前行的查询结果写入上面定义的列中。
dbms_sql.column_value(v_cursor, 2, v_name);
dbms_sql.column_value(v_cursor, 3, v_date);
dbms_output.put_line(v_id || ':' || v_name || ':' || v_date);
end loop;
end;
--------------------------------------------------------------------------------------------------
PL/SQL中使用动态SQL编程
在PL/SQL程序设计过程中,会遇到很多必须使用动态sql的地方,oracle系统所tb提供的DMBS_SQL包可以帮助你解决问题。
(一)介绍
DBMS_SQL系统包提供了很多函数及过程,现在简要阐述其中使用频率较高的几种:
function open_cursor:打开一个动态游标,并返回一个整型;
procedure close_cursor(c in out integer) :关闭一个动态游标,参数为open_cursor所打开的游标;
procedure parse(c in integer, statement in varchar2, language_flag in integer):对动态游标所提供的sql语句进行解析,参数C表示游标,statement为sql语句,language-flag为解析sql语句所用oracle版本,一般有V6,V7跟native(在不明白所连database版本时,使用native);
procedure define_column(c in integer, position in integer, column any datatype, [column_size in integer]):定义动态游标所能得到的对应值,其中c为动态游标,positon为对应动态sql中的位置(从1开始),column为该值所对应的变量,可以为任何类型,column_size只有在column为定义长度的类型中使用如VARCHAR2,CHAR等(该过程有很多种情况,此处只对一般使用到的类型进行表述);
function execute(c in integer):执行游标,并返回处理一个整型,代表处理结果(对insert,delete,update才有意义,而对select语句而言可以忽略);
function fetch_rows(c in integer):对游标进行循环取数据,并返回一个整数,为0时表示已经取到游标末端;
procedure column_value(c in integer, position in integer, value):将所取得的游标数据赋值到相应的变量,c为游标,position为位置,value则为对应的变量;
procedure bind_variable(c in integer, name in varchar2, value):定义动态sql语句(DML)中所对应字段的值,c为游标,name为字段名称,value为字段的值;
以上是在程序中经常使用到的几个函数及过程,其他函数及过程请参照oracle所提供定义语句dbmssql.sql
(二)一般过程
对于一般的select操作,如果使用动态的sql语句则需要进行以下几个步骤: open cursor--->parse--->define column--->excute--->fetch rows--->close cursor;
而对于dml操作(insert,update)则需要进行以下几个步骤: open cursor--->parse--->bind variable--->execute--->close cursor;
对于delete操作只需要进行以下几个步骤: open cursor--->parse--->execute--->close cursor;
(三)具体案例
下面就本人所开发系统中某一程序做分析 该过程为一股票技术曲线计算程序,将数据从即时数据表中取出,并按照计算曲线的公式,tb对这些数据进行计算,并将结果保存到技术曲线表中.
--********************************** --procedure name:R_Ma_Main --入口参数:PID股票代码,PEND时间,pinterval时间间隔,totab目标数据表 --调用函数:R_GetSql1,R_GetSql2 --功能:具体计算单支股票ma技术曲线 --时间:2001-06-20 --********************************** create or replace procedure R_Ma_Main ( pid varchar2, pend varchar2, pinterval varchar2, totab varchar2 ) is --定义数组 type Date_type is table of varchar2(12) index by binary_integer; type Index_type is table of number index by binary_integer;
TempDate Date_Type;--时间数组 TempIndex Index_Type;--股票收盘价数组 TempMa Index_Type;--ma技术曲线数据
cursor1 integer;--游标 cursor2 integer;--游标 rows_processed integer;--执行游标返回
TempInter integer;--参与计算数值个数 TempVal integer;--计算时间类型 TempSql varchar2(500);--动态sql语句 MyTime varchar2(12);--时间 MyIndex number;--数值 MidIndex number;--中间变量 i integer := 999; j integer; begin TempInter := to_number(substr(pinterval,1,4)); TempVal := to_number(substr(pinterval,5,2)); TempSql := R_GetSql1(pid, pend, TempVal);--得到选择数据的sql语句
--得到当天的即时数据,并依次保存到数组中 cursor1 := dbms_sql.open_cursor; --创建游标 dbms_sql.parse(cursor1, TempSql, dbms_sql.native); --解析动态sql语句,取两个字段,时间及价格,其中时间以14位的varchar2表示 dbms_sql.define_column(cursor1, 1, MyTime, 12); --分别定义sql语句中各字段所对应变量 dbms_sql.define_column(cursor1, 2, MyIndex); rows_processed := dbms_sql.execute(cursor1); loop if dbms_sql.fetch_rows(cursor1) > 0 then begin dbms_sql.column_value(cursor1, 1, MyTime); dbms_sql.column_value(cursor1, 2, MyIndex); TempDate(i) := MyTime; TempIndex(i) := MyIndex; i := i - 1;--按倒序的方法填入数组 end; else exit; end if; end loop; dbms_sql.close_cursor(cursor1); --如果取得的数据量不够计算个数,则跳出程序 if i > 999-TempInter then goto JumpLess; end if; --初始化中间变量 MidIndex := 0; TempIndex(i) := 0; for j in i..i+TempInter-1 loop MidIndex := MidIndex + TempIndex(j); end loop;
--依次对当天数据计算ma值,并保存到ma数组中 for j in i+TempInter..999 loop MidIndex := MidIndex - TempIndex(j-TempInter) + TempIndex(j); TempMa(j) := MidIndex/TempInter; end loop;
if TempVal < 6 then--如果计算的是分钟跟天的ma技术曲线 begin cursor2 := dbms_sql.open_cursor; TempSql := 'insert into ' || totab || ' values(:r_no, :i_interval, :i_time, :i_index)'; dbms_sql.parse(cursor2, TempSql, dbms_sql.native); for j in i+TempInter..999 loop dbms_sql.bind_variable(cursor2, 'r_no', pid); dbms_sql.bind_variable(cursor2, 'i_interval', pinterval); dbms_sql.bind_variable(cursor2, 'i_time', TempDate(j)); dbms_sql.bind_variable(cursor2, 'i_index', TempMa(j)); rows_processed := dbms_sql.execute(cursor2);--插入数据 end loop; end; end if; commit; dbms_sql.close_cursor(cursor2); --数据量不足跳出 <<JumpLess>> null; --exception处理,无关本话题 end; /
(四)个人观点
在使用dbms_sql系统包的过程中,其方法简单而又不失灵活,但还是需要注意一些问题:
1、在整个程序的设计过程中,对游标的操作切不可有省略的部分,一旦省略其中某一步骤,则会程序编译过程既告失败,如在程序结尾处未对改游标进行关闭操作,则在再次调用过程时会出现错误. 2、dbms_sql除了可以做一般的select,insert,update,delete等静态的sql做能在过程中所做工作外,还能执行create等DDL操作,不过在执行该类操作时应首先显式赋予执行用户相应的系统权限,比如create table等.该类操作只需open cursor--->prase--->close cursor即能完成.
以上为本人在工作中对dbms_sql的一点点看法,不到之处,请予指正. 对于想更深了解dbms_sql的朋友,请阅读dbmssql.sql文件.
附个Oracle自带的流程说明(强大啊):
-- The flow of procedure calls will typically look like this: -- -- ----------- -- | open_cursor | -- ----------- -- | -- | -- v -- ----- -- ------------>| parse | -- | ----- -- | | -- | | |