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个单位的库存Ud分库里面
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语句后面不能?span style="color: rgb(255,11,242); line-height: 21px">/Q而在创徏PROCEDURE和TRIGGER的之后必d / W号Q否则下面的脚本?/span>
执行p|的?/span>
执行txt和sql的脚本写法如下:
SQL> @ D:\myoracle .txt;
Procedure dropped
Procedure created
Trigger dropped
Trigger created
Commit complete
SQL>
exec 后面执行跟存储过E名或函数名[exec只能在命令行执行Qcall可以在Q何环境下执行]?/div>
]]>
Oracle中DBMS_RANDOM包的用法 http://www.aygfsteel.com/chenhg/archive/2012/09/21/388245.htmlMR.CHEN MR.CHEN Fri, 21 Sep 2012 05:08:00 GMT http://www.aygfsteel.com/chenhg/archive/2012/09/21/388245.html http://www.aygfsteel.com/chenhg/comments/388245.html http://www.aygfsteel.com/chenhg/archive/2012/09/21/388245.html#Feedback 0 http://www.aygfsteel.com/chenhg/comments/commentRss/388245.html http://www.aygfsteel.com/chenhg/services/trackbacks/388245.html 1.dbms_random.valueҎ
dbms_random是一个可以生成随机数值或者字W串的程序包。这个包?/span>initialize ()?/font>seed ()?/font>terminate ()?/font>value ()?/font>normal ()?/font>random ()?/font>string (){几个函敎ͼ但value()是最常用的,value()的用法一般有两个U,W一 function value return number; q种用法没有参数Q会q回一个具?8位精度的数|范围?.0?.0Q但不包?.0Q如下示例: 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 q程已成功完成?nbsp; SQL> W二Uvalue带有两个参数Q第一个指下限Q第二个指上限,会生成下限C限之间的数字Q但不包含上限,“学无止境”兄说的就是第二种Q如下: 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 q程已成功完成?nbsp;
2. dbms_random.string Ҏ
某些用户理E序可能需要ؓ用户创徏随机的密码。?0G下的dbms_random.string 可以实现q样的功能?/p>
例如Q?/div>
SQL> select dbms_random.string('P',8 ) from dual ;
DBMS_RANDOM.STRING('P',8)
--------------------------------------------------------------------------------
3q<M"yf[
W一个参数的含义Q?/div>
■ '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 表示 printableQ即字符串由L可打印字W构?/font>
而第二个参数表示q回的字W串长度?/div>
3. dbms_random.random Ҏ
randomq回的是BINARY_INTEGERcd?产生一个Q意大的随机?/font>
?font face="Arial">dbms_random.value 的区别D?
Order By dbms_random.value; q条语句功能是实现记录的随机排序 另外Q?br />dbms_random.value ?br />dbms_random.random 两者之间有什么区别? 1。Order By dbms_random.value Qؓl果集的每一行计一个随机数Qdbms_random.value 是结果集的一个列Q虽然这个列q不在select list 中)Q然后根据该列排序,得到的顺序自然就是随机的啦?br />2。看看desc信息便知道vlue和randomq两个函数的区别了,valueq回的是numbercdQ?a style="color: #000000" >tbq且q回的g??之间Q而randomq回的是BINARY_INTEGERcdQ以二进制Ş式存储的数字Q据说运的效率高于number但我没测试过Q但取D围肯定小于numberQ具体限制得查资料了Q?br />如果你要实现随机排序Q还是用value函数?/font>
4. dbms_random.normalҎ
NORMAL函数q回服从正态分布的一l数。此正态分布标准偏差ؓ1Q期望gؓ0。这个函数返回的数g?8%是介?1?1之间Q?5%介于-2?2之间Q?9%介于-3?3之间?/font>
5. dbms_random.sendҎ
用于生成一个随机数U子,讄U子的目的是可以重复生成随机敎ͼ用于调试。否则每ơ不同,难以调度?/span>
]]>
Oracle中DBMS_SQL的用?/title> http://www.aygfsteel.com/chenhg/archive/2012/09/21/388244.htmlMR.CHEN MR.CHEN Fri, 21 Sep 2012 05:07:00 GMT http://www.aygfsteel.com/chenhg/archive/2012/09/21/388244.html http://www.aygfsteel.com/chenhg/comments/388244.html http://www.aygfsteel.com/chenhg/archive/2012/09/21/388244.html#Feedback 0 http://www.aygfsteel.com/chenhg/comments/commentRss/388244.html http://www.aygfsteel.com/chenhg/services/trackbacks/388244.html 对于一般的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;
例一Q?/div>
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); --l定变量
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;
例二Q?/div>
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;
例三Q?/div>
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;
例四Q?/div>
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); --定义?/font>
dbms_sql.define_column(v_cursor, 2, v_name, 50); --注意Q当变量为varchar2cdӞ要加长度
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在结果集中移动游标,如果未抵达末,q回1?/font>
dbms_sql.column_value(v_cursor, 1, v_id); --当前行的查询结果写入上面定义的列中?/font>
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/SQLE序设计q程中,会遇到很多必M用动态sql的地方,oraclepȝ所tb 提供的DMBS_SQL包可以帮助你解决问题?br />
(一)介绍
DBMS_SQLpȝ包提供了很多函数及过E?现在要阐q其中用频率较高的几种: function open_cursor :打开一个动态游?q返回一个整? procedure close_cursor(c in out integer) : 关闭一个动态游?参数为open_cursor所打开的游? procedure parse(c in integer, statement in varchar2, language_flag in integer) :对动态游标所提供的sql语句q行解析,参数C表示游标,statement为sql语句,language-flag析sql语句所用oracle版本,一般有V6,V7跟native(在不明白所qdatabase版本?使用native); procedure define_column(c in integer, position in integer, column any datatype, [column_size in integer]) :定义动态游标所能得到的对应?其中c为动态游?positon为对应动态sql中的位置(?开?,column值所对应的变?可以ZQ何类?column_size只有在column为定义长度的cd中用如VARCHAR2,CHAR{?该过E有很多U情?此处只对一般用到的类型进行表q?; function execute(c in integer) :执行游标,q返回处理一个整?代表处理l果(对insert,delete,update才有意义,而对select语句而言可以忽略); function fetch_rows(c in integer) :Ҏ标进行@环取数据,q返回一个整??时表C已l取到游标末? procedure column_value(c in integer, position in integer, value) :所取得的游标数据赋值到相应的变?c为游?positionZ|?value则ؓ对应的变? procedure bind_variable(c in integer, name in varchar2, value) :定义动态sql语句(DML)中所对应字段的?c为游?name为字D名U?value为字D늚? 以上是在E序中经怋用到的几个函数及q程,其他函数及过E请参照oracle所提供定义语句dbmssql.sql
(?一般过E?/font>
对于一般的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;
(?具体案例
下面本人所开发系l中某一E序做分?br /> 该过Eؓ一股票技术曲U计程?数据从x数据表中取出,q按照计曲U的公式,tb 对这些数据进行计?q将l果保存到技术曲U表?
--********************************** --procedure name:R_Ma_Main --入口参数QPID股票代码,PEND旉,pinterval旉间隔,totab目标数据?br />--调用函数QR_GetSql1,R_GetSql2 --功能Q具体计单支股ma技术曲U?br />--旉Q?001-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;--股票收盘hl?br />TempMa Index_Type;--ma技术曲U数?br /> cursor1 integer;--游标 cursor2 integer;--游标 rows_processed integer;--执行游标q回 TempInter integer;--参与计算数g?br />TempVal integer;--计算旉cd TempSql varchar2(500);--动态sql语句 MyTime varchar2(12);--旉 MyIndex number;--数?br />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语句 --得到当天的即时数?q依ơ保存到数组?br /> cursor1 := dbms_sql.open_cursor; --创徏游标 dbms_sql.parse(cursor1, TempSql, dbms_sql.native); --解析动态sql语句,取两个字D?旉及h?其中旉?4位的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;--按倒序的方法填入数l?br /> end; else exit; end if; end loop; dbms_sql.close_cursor(cursor1); --如果取得的数据量不够计算个数,则蟩出程?br /> if i > 999-TempInter then goto JumpLess; end if; --初始化中间变?br /> MidIndex := 0; TempIndex(i) := 0; for j in i..i+TempInter-1 loop MidIndex := MidIndex + TempIndex(j); end loop; --依次对当天数据计ma?q保存到ma数组?br /> 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技术曲U?br /> 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); --数据量不?br /> <<JumpLess>> null; --exception处理,无关本话?br />end; /
(?个h观点
在用dbms_sqlpȝ包的q程?其方法简单而又不失灉|,但还是需要注意一些问?
1、在整个E序的设计过E中,Ҏ标的操作切不可有省略的部?一旦省略其中某一步骤,则会E序~译q程既告p|,如在E序l尾处未Ҏ游标q行关闭操作,则在再次调用q程时会出现错误. 2、dbms_sql除了可以做一般的select,insert,update,delete{静态的sql做能在过E中所做工作外,q能执行create{DDL操作,不过在执行该cL作时应首先显式赋予执行用L应的pȝ权限,比如create table{?该类操作只需open cursor--->prase--->close cursor卌完成. 以上为本人在工作中对dbms_sql的一点点看法,不到之处,请予指正. 对于x׃解dbms_sql的朋?请阅读dbmssql.sql文g.
附个Oracle自带的流E说?强大?Q?/span>
-- The flow of procedure calls will typically look like this: -- -- ----------- -- | open_cursor | -- ----------- -- | -- | -- v -- ----- -- ------------>| parse | -- | ----- -- | | -- |