700 likes | 882 Views
实用工具包. 输入输出 文件 I/O 动态 SQL 语句 作业处理. 2002. DBMS_OUTPUT 包与输入输出. 为 PL/SQL 程序提供了对一个内部缓冲区的输入与输出功能。 触发器 PUT 存储过程 GET 包体. 缓冲区. DBMS_OUTPUT 包的输出过程. 输出基本数据 PROCEDURE PUT ( a VARCHAR2) ; PROCEDURE PUT ( a NUMBER) ; PROCEDURE PUT ( a DATE) ;
E N D
实用工具包 输入输出 文件I/O 动态SQL语句 作业处理 2002
DBMS_OUTPUT包与输入输出 • 为PL/SQL程序提供了对一个内部缓冲区的输入与输出功能。 • 触发器 PUT • 存储过程 GET • 包体 缓冲区
DBMS_OUTPUT包的输出过程 • 输出基本数据 • PROCEDURE PUT(a VARCHAR2) ; • PROCEDURE PUT(a NUMBER) ; • PROCEDURE PUT(a DATE) ; • 输出一行数据(数据+换行符) • PROCEDURE PUT_LINE(a VARCHAR2) ; • PROCEDURE PUT_LINE(a NUMBER) ; • PROCEDURE PUT_LINE(a DATE) ; • PROCEDURE NEW_LINE ; • PUT_LINE 等价于: PUT + NEW_LINE • 每一行最多可存入255个字节
DBMS_OUTPUT包的输出过程 • PROCEDURE GET_LINE(line OUT VARCHAR2 , status OUT INTEGER) ; • line——从缓冲区读入的一行数据 • status——0:读入成功,1 读入失败 • PROCEDURE GET_LINES(lines OUT CHARARR , numlines IN OUT INTEGER) ; • lines是一个PL/SQL表,它包含了取自缓冲区的多行数据。 • numlines指定了需要读取的行数。而当过程执行完毕,参数numlines的值就是返回行的实际数目。 TYPE CHARARR IS TABLE OF VARCHAR2(255) INDEX BY BINARY_INTEGER ;
其他过程 • PROCEDURE ENABLE(buffer_size IN INTEGER DEFAULT 20000) ; • buffer_size——指定缓冲区大小。单位是字节, • 初始值为20000,最大值不能超过1000000字节。 • PROCEDURE DISABLE ; • 清除缓冲区内容,并使该缓冲区不可使用。 • 调用了DISABLE过程后,上面那些对内部缓冲区的读写过程将不起作用。
重置缓冲区 PROCEDURE reset_buffer(b_size IN INTEGER) AS BEGIN DBMS_OUTPUT.DISABLE; DBMS_OUTPUT.ENABLE(b_size); END ;
输入/输出例 DECLARE /*-使用包类型定义变量(PL/SQL表)*/ v_Data DBMS_OUTPUT.CHARARR; v_NumLines NUMBER; BEGIN --设置内部缓冲区大小 DBMS_OUTPUT.ENABLE(1000000); -- 向缓冲区放入一些数据 DBMS_OUTPUT.PUT_LINE('Line One'); DBMS_OUTPUT.PUT_LINE('Line Two'); DBMS_OUTPUT.PUT('Line Three'); DBMS_OUTPUT.NEW_LINE ;
输入/输出例 --设置将从缓冲区中取出的行数 v_NumLines := 3; --读取缓冲区的内容 DBMS_OUTPUT.GET_LINES(v_Data, v_NumLines); -- 将读出的内容存入数据库表中 FOR v_Counter IN 1..v_NumLines LOOP INSERT INTO temp_table (char_col) VALUES (v_Data(v_Counter)); END LOOP; END; /
PL/SQL打印输出 • DBMS_OUTPUT包本身并不包含打印输出的任何机制,它实际上只是实现了先进先出的数据结构。 • SQL*Plus和Server Manager都有一个SERVEROUTPUT的选项,该选项可以将内部缓冲区的内容打印输出。 • 当打开这个选项后,在一个PL/SQL程序结束时,系统会自动调用DBMS_OUTPUT.GET_LINES过程,并输出内部缓冲区的内容。
PL/SQL打印输出例 BEGIN DBMS_OUTPUT.PUT_LINE('aaaaa'); DBMS_OUTPUT.PUT('bbbbb'); DBMS_OUTPUT.PUT_LINE('ccccc'); END; • 下面是执行该段代码的过程: SQL> @a PL/SQL 过程已成功完成。 SQL> set serveroutput on SQL> @a aaaaa bbbbbccccc PL/SQL 过程已成功完成。
PL/SQL打印输出例 DECLARE v_data varchar2(50); v_status INTEGER; BEGIN DBMS_OUTPUT.PUT_LINE('aaaaa'); DBMS_OUTPUT.GET_LINE(v_data, v_status); DBMS_OUTPUT.PUT_LINE('=='||v_data||’==’); DBMS_OUTPUT.PUT_LINE('bbbbb'); DBMS_OUTPUT.PUT_LINE('ccccc'); END; ==aaaaa== bbbbb ccccc
UTL_FILE包与文件I/O • UTL_FILE包为PL/SQL程序增加了对于操作系统文件的I/O功能。 数据库 文件
打开文件 FUNCTION FOPEN ( location IN VARCHAR2, --目录 filename IN VARCHAR2, --文件名(包括扩展名) open_mode IN VARCHAR2 -- 文件打开模式 ) RETURN UTL_FILE.FILE_TYPE ; • ‘r’ 读文本模式(GET_LINE) • ‘w’ 写文本模式(PUT, PUT_LINE, NEW_LINE, UTF, FFLUSH) • ‘a’ 追加模式(PUT, PUT_LINE, NEW_LINE, PUTF, FFLUSH) • FOPEN返回一个文件指针,该指针必须通过参数传递给所有操作文件的过程。 • 在打开文件操作中,文件位置和文件名是作为两个参数分别指定的。两者结合起来必须代表一个合法的操作系统文件。
关闭文件 PROCEDURE FCLOSE(file_handle IN FILE_TYPE) ; • 执行该过程可能引起的例外: • UTL_FILE.WRITE_ERROR 在关闭文件时,有些缓冲区的数据要写入文件,所以可能产生写文件错误。 • UTL_FILE.INVALID_FILEHANDLE • 关闭所有打开的文件 PROCEDURE FCLOSE_ALL ; • 该过程关闭所有打开的文件。常用于紧急情况下的关闭过程,例如在例外处理完退出程序时可调用它。
读文件 PROCEDURE GET_LINE ( file_handle IN FILE_TYPE, buffer OUT VARCHAR2 ); • 参数说明: • file_handle 一个已被FOPEN打开的文件指针,且打开模式为‘r’。 • buffer 接收从文件中读出的一行数据。 • 该过程从文件中读出一行文本,并放入buffer参数中。由于行结束符并不读入buffer中,所以读一空行将返回一个空字符串。读入记录最大不超过1022字节。
写文件 • PROCEDURE PUT( file_handle IN FILE_TYPE, buffer IN VARCHAR2 ); • 参数说明: • file_handle 一个已被FOPEN打开的文件指针,且打开模式为‘w’或‘a’。 • buffer 包含写入文件的数据。 • PUT过程将buffer内容写入文件,但不追加任何行结束符。 PROCEDURE PUT_LINE( file_handle IN FILE_TYPE, buffer IN VARCHAR2 ) ; • 在写入数据后面追加行结束符。一个输出记录的大小不能超过1023字节。
格式化写文件 PROCEDURE PUTF( file_handle IN FILE_TYPE, format IN VARCHAR2, [arg1 IN VARCHAR2 , … arg5 IN VARCHAR2] ); • 参数说明: • file_handle:一个已被FOPEN打开的文件指针。 • format:格式串,由输出文本及格式符组成。 • arg1…arg5: 为1到5个可选的替换串,用于替换格式串中的%s格式字符。 • PUTF是一个格式化的PUT过程,它允许在输出数据中夹带一些称之为格式符的替换符和换行符,这些格式符不属于输出字符的内容。格式符只有两个: l % s:替换符,表示该位置由相应的arg参数值替换。 l \n :换行符,表示该位置插入一个换行符。
格式化写文件例 my_city := ‘Beijing’ ; PUTF(f1_handle , ‘Hello world ! \n I come from %s and she come from %s.\n ’ , my_city , ‘Shanghai ’); • 该PUTF写语句写入文件的内容如下: Hello world ! I come from Beijing and she come from Shanghai . • 其中,第一个%s由字符串变量my_city(即arg1)的值替换 • 第二个%s由字符串‘Shinghai’(即arg2)替换。 • 如果格式串中的%s个数比后面的arg参数多,则多出的%s就用空串替代。
其他文件操作过程 • 写行结束符 PROCEDURE NEW_LINE( file_handle IN FILE_TYPE, lines IN NATURAL :=1 ); • 该过程在文件的当前位置写入换行符。参数lines表示写入的换行符个数,隐含值为1。 • 刷新文件 PROCEDURE FFLUSH ( file_handle IN FILE_TYPE) ; • 该过程物理地将所有余留在缓冲区中的数据写入文件。 • 当文件还处于打开状态时,在读文件之前,应使用FFLUSH过程,这样读出的是你写入的全部数据。
文件访问权限设置 • 数据库管理员在Oracle系统中进行设置: • 在数据库实例的参数初始化文件(INIT.ORA)中,指定UTL_FILE包可以访问的目录,UTL_FILE_DIR = /oracle/wxy/dbfile UTL_FILE_DIR = /oracle/wxy/dbfile /d1 • 注:每个可访问目录通过初始化文件中的一行来标识。 • 当指定了一个可访问目录后,并不意味着它下面的子目录也都可以访问。 • UTL_FILE_DIR = * 取消数据库限制
文件访问权限设置 • UTL_FILE执行的文件I/O操作将被视为Oracle用户的操作。因此,Oracle用户必须拥有对有关文件的读写权限,否则UTL_FILE包对予这些目录和文件的访问将会被操作系统所禁止。 • 系统管理员在UNIX系统中进行权限设置。 $> cd /oracle/wxy $>chgrp dba dbfile $>chmod 770 dbfile $>ls –l drwxrwx--- 3 wxy dba 512 8月1 20:49 dbfile
文件访问权限设置 $> cd dbfile $> ls –l drwxrwxr-x 2 wxy dba 512 8月1 16:17 d1 -rw-r--r-- 1 wxy dba 58 8月1 22:46 f1 文件可读 -rw-r--r-- 1 wxy dba 58 8月1 23:46 f2 文件可读 $> chmod 664 f2 $> ls –l drwxrwxr-x 2 wxy dba 512 8月1 16:17 d1 -rw-r--r-- 1 wxy dba 58 8月1 22:46 f1 文件可读 -rw-rw-r-- 1 wxy dba 58 8月1 23:46 f2 文件可写可读
读文件例 • /oracle/wxy/dbfile目录下有一个文本文件f1,该文件包含职工记录如下 : e01, aaa, 23, 500, d01 e02, bbb, 33, 800, d01 e03, ccc, 47, 900, d02 • 程序从该文件读入数据,并将职工信息插入到emp1表中,emp1表的列与f1文件的各项一一对应。
读文件例 DECLARE v_fp UTL_FILE.FILE_TYPE; --定义文件指针变量 v_line VARCHAR2(80); a INTEGER ; b INTEGER ; e emp1%ROWTYPE ; BEGIN v_fp:=UTL_FILE.FOPEN( '/oracle/wxy/dbfile' , 'f1' , 'r' ) ; LOOP --每次循环,从文件中读取一行数据 BEGIN UTL_FILE.GET_LINE(v_fp , v_line) ; EXCEPTION WHEN NO_DATA_FOUND THEN EXIT ; --文件读完,退出循环 END ;
读文件例 b := 0 ; /* 以下是以逗号为分界符,分开读入记录的各项内容 */ a := b+1 ; b := INSTR(v_line , ‘,’ , 1 , 1 ) ; --查找第一个逗号位置 e.eno := SUBSTR(v_line , a , b-a) ; --取出第一项内容 a := b +1 ; b := INSTR(v_line , ‘,’ , 1 , 2 ) ; --查找第二个逗号位置 e.ename := SUBSTR(v_line , a , b-a) ; --取出第二项内容 a := b+1 ; b := INSTR(v_line , ‘,’ , 1 , 3 ) ; e.age := TO_NUMBER( SUBSTR(v_line , a , b-a) , 99) ; a := b+1 ; b := INSTR(v_line , ‘,’ , 1 , 4 ) ; e.sal := TO_NUMBER( SUBSTR(v_line , a , b-a) , 9999.99) ;
读文件例 a := b+1 ; e.dno := SUBSTR(v_line , a) ; --取出最后一项 INSERT INTO emp1 VALUES(e.eno,e.ename,e.age,e.sal,e.dno) ; END LOOP ; UTL_FILE.FCLOSE(v_fp) ; --关闭文件 EXCEPTION WHEN UTL_FILE.INVALID_OPERATION THEN UTL_FILE.FCLOSE(v_fp) ; RAISE_APPLICATION_ERROR(-20001, ‘invalid operation’) ; WHEN UTL_FILE.INVALID_FILEHANDLE THEN UTL_FILE.FCLOSE(v_fp) ; RAISE_APPLICATION_ERROR(-20002, ‘invalid file handle’) ;
读文件例 WHEN UTL_FILE.READ_ERROR THEN UTL_FILE.FCLOSE(v_fp) ; RAISE_APPLICATION_ERROR(-20003, ‘read error’) ; WHEN OTHERS THEN UTL_FILE.FCLOSE(v_fp) ; RAISE ; END; /
写文件例 • 建立一个存储过程,其功能是接收一名职工号,然后向指定文件输出该名职工的基本信息和所在部门的有关信息(如部门的名称、电话和职工总数等)。写入的文件名及目录也作为过程的参数。过程定义如下: CREATE PROCEDURE emp_file( e_no CHAR , f_dir VARCHAR2 , f_name VARCHAR2 ) AS v_fp UTL_FILE.FILE_TYPE ; e_rec emp1%ROWTYPE ; d_rec dep1%ROWTYPE ; v_total INTEGER ;
写文件例 BEGIN v_fp := UTL_FILE.FOPEN(f_dir , f_name , ‘w’) ; --写模式 SELECT * INTO e_recFROM emp1 WHERE eno = e_no ; UTL_FILE.PUTF( v_fp , ‘employee ID : %s\n’ ,e_rec.eno ) ; UTL_FILE.PUTF( v_fp , ‘employee name : %s\n’ , e_rec.ename ) ; UTL_FILE.PUTF( v_fp , ‘employee age : %s\n’ , TO_CHAR(e_rec.age,‘99’) ) ; UTL_FILE.PUTF( v_fp , ‘employee salary : %s\n’ , TO_CHAR(e_rec.sal, ‘9999.99’ )) ; UTL_FILE.PUTF( v_fp , ‘department ID : %s\n’ ,e_rec.dno ) ;
写文件例 SELECT * INTO d_rec --读取职工所在部门信息 FROM dep1 WHERE dno= e_rec.dno ; SELECT COUNT(*) INTO v_total --统计职工所在部门人数 FROM emp1 WHERE dno=e_rec.dno ; UTL_FILE.PUT_LINE(v_fp , ‘------------------------------------’) ; UTL_FILE.PUTF( v_fp , ‘department name : %s\n’ , d_rec.dname ) ; UTL_FILE.PUTF( v_fp , ‘department tel : %s\n’ ,d_rec.tel ) ; UTL_FILE.PUTF( v_fp , ‘employees of department : %s人\n’ , TO_CHAR(v_total ,‘9999’)) ; UTL_FILE.PUTF( v_fp , ‘printed on : %s\n ’ , TO_CHAR(SYSDATE ,‘YYYY/MON/DD’ ) );
写文件例 UTL_FILE.FCLOSE( v_fp ) ; EXCEPTION WHEN UTL_FILE.INVALID_OPERATION THEN UTL_FILE.FCLOSE(v_fp) ; RAISE_APPLICATION_ERROR(-20001, ‘stu_file : invalid operation’) ; WHEN OTHERS THEN UTL_FILE.FCLOSE(v_fp) ; RAISE ; END; /
写文件例 SQL> exec emp_file('e01','/oracle/wxy/dbfile','f2') employee ID : e01 f2文件内容 employee name : aaa employee age : 23 employee salary : 500.00 department ID : d01 ------------------------------------ department name : 佳月公司 department tel : 627829 employees of department : 2人 printed on : 2001/8月 /01
DBMS_SQL包与动态SQL语句 • 静态SQL是指SQL语句的结构在编译时都已确定 DECLARE v_eno emp.eno%TYPE := ‘e01’ ; v_inc NUMBER ; BEGIN v_inc := 200 ; UPDATE emp SET sal =sal + v_inc WHERE eno = v_eno ; END ; • 变量只是为语句提供数据,并没有改变语句本身。
DBMS_SQL包与动态SQL语句 • 动态SQL是指在PL/SQL程序运行时,构造出一个SQL语句并执行它,编译阶段是分析不出该语句的 • 构造SQL语句的过程是一个拼接字符串的过程 。 • 利用DBMS_SQL包的过程执行动态SQL • 使用DBMS_SQL.OPEN_CURSOR打开一个光标,并返回光标id号。为下面构造的sql语句的执行做好准备。 • 使用DBMS_SQL.PARSE 分析该字符串中的语句。 • 使用DBMS_SQL.BIND_VARIABLE为sql语句中的参数赋值(联编输入变量)。 • 使用DBMS_SQL.DEFINE_COLUMN定义一个输出变量。
DBMS_SQL包与动态SQL语句 • 利用DBMS_SQL包的过程 • 使用DBMS_SQL.EXECUTE执行 sql语句。 • 当执行非查询语句,返回处理了的行数 • 当执行查询语句,返回一个结果集 • DBMS_SQL.FETCH_ROWS 提取查询数据。 • DBMS_SQL.COLUMN_VALUE 将查询结果(FETCH提取出来的)返回给PL/SQL变量。 • DBMS_SQL.CLOSE_CURSOR 关闭光标
动态写语句 DECLARE v_cid INTEGER ; --定义存放光标id号的变量 v_updatestr VARCHAR2(100) ; --定义字符串变量,存放被构造的SQL语句 v_rowsupdated INTEGER ; BEGIN v_cid :=DBMS_SQL.OPEN_CURSOR ; --打开光标 --构造语句 v_updatestr :=‘update course set credit= 4 where cno= ‘’c01‘’ ’ ; --解析语句 DBMS_SQL.PARSE(v_cid , v_updatestr , DBMS_SQL.V7) ; --执行动态SQL语句 v_rowsupdated := DBMS_SQL.EXECUTE(v_cid) ; DBMS_SQL.CLOSE_CURSOR(v_cid) ; --关闭光标
动态写语句 EXCEPTION WHEN OTHERS THEN DBMS_SQL.CLOSE_CURSOR(v_cid) ; RAISE ; END ;
动态写语句(带参数) CREATE FUNCTION updatecredit ( p_cno IN course.cno%TYPE , p_newcredit IN course.credit%TYPE ) RETURN INTEGER AS v_cid INTEGER ; v_updatestr VARCHAR2(100) ; p_rowsupdated INTEGER ; BEGIN v_cid := DBMS_SQL.OPEN_CURSOR ; v_updatestr :=‘update course set credit= :crd where cno= :cno’ ; DBMS_SQL.PARSE(v_cid , v_updatestr , DBMS_SQL.V7) ; DBMS_SQL.BIND_VARIABLE(v_cid , ‘crd’ , p_newcredit) ; DBMS_SQL.BIND_VARIABLE(v_cid , ‘cno’ , p_cno) ; p_rowsupdated := DBMS_SQL.EXECUTE(v_cid) ;
动态写语句(带参数) DBMS_SQL.CLOSE_CURSOR(v_cid) ; RETURN p_rowsupdated ; EXCEPTION WHEN OTHERS THEN DBMS_SQL.CLOSE_CURSOR(v_cid) ; RAISE ; END ;
动态读语句 • 解决返回值的问题 • 在执行之前,使用DEFINE_COLUMN定义输出变量的类型和长度。 • 在执行之后,调用FETCH_ROWS读取一行数据。 • 利用COLUMN_VALUE取出指定的列值。 • 例: 程序从emp1表中检索出指定部门的职工,并将他们的信息插入到emp2表中。
动态读语句 DECLARE v_cid INTEGER; v_select VARCHAR2(100); v_insert VARCHAR2(100); v_eno CHAR(3); v_ename VARCHAR2(10); v_dno CHAR(3); v_Dummy INTEGER ; BEGIN v_cid := DBMS_SQL.OPEN_CURSOR; -- 构造查询串 v_select := 'SELECT eno,ename,dno FROM emp1 WHERE dno = ‘’d01’’‘ ; DBMS_SQL.PARSE(v_cid ,v_select ,DBMS_SQL.V7);
动态读语句 -- 定义输出变量 DBMS_SQL.DEFINE_COLUMN(v_cid, 1, v_eno, 3); DBMS_SQL.DEFINE_COLUMN(v_cid, 2, v_ename, 10); DBMS_SQL.DEFINE_COLUMN(v_cid, 3, v_dno, 3); v_Dummy := DBMS_SQL.EXECUTE(v_cid); LOOP IF DBMS_SQL.FETCH_ROWS(v_cid) = 0 THEN EXIT; END IF; DBMS_SQL.COLUMN_VALUE(v_cid, 1, v_eno); DBMS_SQL.COLUMN_VALUE(v_cid, 2, v_ename); DBMS_SQL.COLUMN_VALUE(v_cid, 3, v_dno); INSERT INTO emp2(eno,ename,dno) VALUES (v_eno,v_ename,v_dno);
动态读语句 END LOOP; DBMS_SQL.CLOSE_CURSOR(v_cid); COMMIT; EXCEPTION WHEN OTHERS THEN DBMS_SQL.CLOSE_CURSOR(v_cid); RAISE; END ; /
动态DDL语句 对DDL语句的处理和对DML语句的处理有以下两点不同: • 因为在DDL语句中联编变量是非法的(即语句中不允许出现占位符),所以在进行解析之后也不需要调用BIND_VARIABLE过程。 • DDL语句解析后立即执行。DDL语句是在调用PARSE时被执行的,所以不必调用EXECUTE函数。(即使写上了EXECUTE函数,它也不起什么作用)。
动态DDL语句例 • 建一存储过程。功能:删除并重建指定的关系表 CREATE PROCEDURE RecreateTable ( p_table IN VARCHAR2 , p_Description IN VARCHAR2) IS v_Cursor NUMBER; v_CreateS VARCHAR2(100); v_DropS VARCHAR2(100); BEGIN v_Cursor := DBMS_SQL.OPEN_CURSOR; --打开光标 /* 删除表处理 */ v_DropS := 'DROP TABLE ' || p_table ;
动态DDL语句例 /* 解析DROP TABLE 语句并执行它。执行时可能出现ORA-942错误,即表不存在。下面的嵌套块将处理此例外 */ BEGIN DBMS_SQL.PARSE(v_Cursor, v_DropS, DBMS_SQL.V7); EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END; /* 建立表处理,首先建立CREATE TABLE字符串,然后解析并执行它*/ v_CreateS := 'CREATE TABLE ' || p_table || p_Description ; DBMS_SQL.PARSE(v_Cursor, v_CreateS, DBMS_SQL.V7);
动态DDL语句例 DBMS_SQL.CLOSE_CURSOR(v_Cursor); EXCEPTION WHEN OTHERS THEN DBMS_SQL.CLOSE_CURSOR(v_Cursor); RAISE; END ; /
动态DDL语句例2 CREATE PROCEDURE exec( s IN VARCHAR2) AS cid INTEGER ; BEGIN cid := DBMS_SQL.OPEN_CURSOR ; DBMS_SQL.PARSE( cid , s , DBMS_SQL.V7 ) ; DBMS_SQL.CLOSE_CURSOR( cid ) ; END ; / BEGIN exec(‘drop table temp’) ; --调用exec过程 END ;
OPEN_CURSOR 函数 DBMS_SQL.OPEN_CURSOR RETURN INTEGER ; • 打开一个新的光标。系统将返回一个光标ID号。 • 利用光标可以执行动态SQL语句。 • 使用一个光标可以反复执行一条SQL语句,也可以执行不同的SQL语句。光标的反复使用并不需要关闭再打开的操作。 • 注意:此处的光标与在PL/SQL中定义的光标以及系统予定义光标不同,它们仅用于DBMS_SQL包。
PARSE 过程 DBMS_SQL.PARSE( c IN INTEGER , statement IN VARCHAR2 , language_fiag IN INTSGER) ; • 该过程对给定的SQL语句进行解析。解析语句的目的是对语句进行语法检查,并将该语句与其在程序中打开的光标相连。这时执行动态SQL之前的必要一步。 • 参数说明: • c :指定光标的ID号,该ID号是在打开光标时获得的。 • statement: 提供要解析的SQL语句。语句不要包括结束的分号。 • language_fiag:该参数决定Oracle 如何处理SQL 语句。 DBMS_SQL.V7 :采用Oracle 7 方式 • PARSE可以解析任何DML语句和DDL语句。当解析的是DDL语句时,PARSE在解析之后就立即执行该语句。