PL/SQL Challenge 每日一题:2015-8-10 DBMS_SQL: 解析超长字符串

[复制链接]
查看11 | 回复7 | 2008-9-15 01:28:12 | 显示全部楼层 |阅读模式
(原发表于2010-12-22)

最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可发新贴补充或纠正),其他会员如果提供有价值的分析、讨论也可获得纪念章一枚。
以往旧题索引:
http://www.itpub.net/forum.php?m ... eid&typeid=1808
原始出处:
http://www.plsqlchallenge.com/
作者:Steven Feuerstein
运行环境:SQLPLUS, SERVEROUTPUT已打开
注:本题给出答案时候要求给予简要说明才能得到奖品
注:本题执行环境为11g以上
我需要写一个过程,它使用的是动态SQL, 执行的内容来自一个文件,里面是一个DDL语句。换言之,我的文件内容看起来可能是这样:
CREATE OR REPLACE PROCEDURE new_procedure
IS
BEGIN
NULL;
END;
文件的大小(字节数)可能超过32,767。哪些选项描述了PL/SQL的一项功能,我可以用来实现这个过程?
(A)
你可以用DBMS_SQL包的一个子程序来解析一个长度超过32767字节的SQL语句。

(B)
你不能够把一个长度超过32767字节的字符串作为动态SQL语句来执行。

(C)
在 Oracle11g, 你可以将一个CLOB传给 EXECUTE IMMEDIATE.
(D)
调用 UTL_FILE.EXEC_FILE_AS_DDL 过程,将文件的目录和名字传给它。UTL_FILE会为我们完成所有工作!

(E)
调用 DBMS_SQL.EXEC_FILE_AS_DDL 过程,将文件的目录和名字传给它。DBMS_SQL会为我们完成所有工作!

回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
A.是正确的,以前可以使用DBMS_SQL的VARCHAR2S接口进行切割,现在直接传clob就好啦
B.也是正确的,哪有字符串能存超过32767的。胡闹,除非是clob。
C.也是正确的,现在这样弄方便多了。
DE恕我眼拙,我闻所未闻有这两个东西存在,否则的话,大家也不用去解析文件啦~~!
我选ABC
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
A:印象中DBMS_SQL的statement是用VARCHAR2傳入。故應該是不可超過Varchar2限制。(解讀DATA的內容類型是可以CLOB)
B:都說字串VARCHAR限制是32767了!當然就是不可以囉~~
C:基本上CLOB也是字串。故提交後應該是沒問題的!!
D、E:我在這兩個內建包中,似乎是沒有這兩個Function!!
故我選B、C
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
superking915 发表于 2015-8-13 08:07
A:印象中DBMS_SQL的statement是用VARCHAR2傳入。故應該是不可超過Varchar2限制。(解讀DATA的內容類型是可以 ...

只有B说了是字符串哦。A可没说是字符串。
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
我知道A是說超過32767的字符。但DBMS_SQL的子程序的接收段的腳本都是設定成VARCHAR2。
故我認為不可以!!
即便您說切割後傳入...因SQL經切割後在DBMS_SQL內也無法合併,故解析出的SQL可能非本意或
者失敗!!還是說這選項是指內容!?
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
A:这个可以,原理是拆分成块,最后一块执行dbms_sql.varchar2s
B:字符串超过32767,11g可以用clob了
C:是对的
D、E:没用过,看着这个方法EXEC_FILE_AS_DDL 看来只能执行ddl语句的样子。
我选 AC
回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
答案AC, 6楼得奖。2楼关于字符串的说法有点钻牛角尖,SQL的VARCHAR2还不能超过4000呢(12C之前)?
A:
这些过载子程序的头部是这样的:
procedure parse(c in integer, statement in varchar2a,

lb in integer, ub in integer,

lfflg in boolean, language_flag in integer);
procedure parse(c in integer, statement in varchar2s,

lb in integer, ub in integer,

lfflg in boolean, language_flag in integer);

varchar2a 和 varchar2s 标识符是关联数组类型。下面是一个例子,它使用varchar2a过载子程序来将一个文件加载入数组并且作为动态DDL执行:

CREATE OR REPLACE PROCEDURE exec_ddl_from_file (
dir_in IN VARCHAR2
, file_in IN VARCHAR2
)
IS
l_fileUTL_FILE.file_type;
l_eof BOOLEAN;
l_lines DBMS_SQL.varchar2a;
PROCEDURE get_next_line (line_out OUT VARCHAR2, eof_out OUT BOOLEAN)
IS
BEGIN
UTL_FILE.get_line (l_file, line_out);
eof_out := FALSE;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
line_out := NULL;
eof_out := TRUE;
END get_next_line;
PROCEDURE exec_ddl_statement (lines_in IN DBMS_SQL.varchar2a)
IS
l_curINTEGER;
l_exec PLS_INTEGER;
BEGIN
l_cur := DBMS_SQL.open_cursor;
DBMS_SQL.parse (l_cur

, l_lines

, l_lines.FIRST

, l_lines.LAST

, TRUE

, DBMS_SQL.native

);
l_exec := DBMS_SQL.EXECUTE (l_cur);
DBMS_SQL.close_cursor (l_cur);
END exec_ddl_statement;
BEGIN
l_file := UTL_FILE.fopen (dir_in, file_in, 'R');
LOOP
get_next_line (l_lines (l_lines.COUNT + 1), l_eof);
EXIT WHEN l_eof;
END LOOP;
UTL_FILE.fclose (l_file);

exec_ddl_statement (l_lines);
END exec_ddl_from_file;

B: 错误。你可以用DBMS_SQL.PARSE的两种过载,它们接受一个包含多行文本的集合,组合起来就构成动态执行的语句。另外,在Oracle11g,你可以传递一个CLOB给EXECUTE IMMEDIATE.
C: 正确,这里是一个利用此功能的例子:
CREATE OR REPLACE PROCEDURE exec_ddl_from_file (dir_inIN VARCHAR2

, file_in IN VARCHAR2)
IS
l_file UTL_FILE.file_type;
l_eofBOOLEAN;
l_line VARCHAR2 (32767);
l_ddlCLOB;
PROCEDURE get_next_line (line_out OUT VARCHAR2, eof_out OUT BOOLEAN)
IS
BEGIN
UTL_FILE.get_line (l_file, line_out);
eof_out := FALSE;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
line_out := NULL;
eof_out := TRUE;
END get_next_line;
BEGIN
l_file := UTL_FILE.fopen (dir_in, file_in, 'R');
LOOP
get_next_line (l_line, l_eof);
EXIT WHEN l_eof;
l_ddl := l_ddl || CHR (10) || l_line;
END LOOP;
UTL_FILE.fclose (l_file);
EXECUTE IMMEDIATE l_ddl;
END exec_ddl_from_file;
/
D,E: 不幸的是,这样的过程不存在。

回复

使用道具 举报

千问 | 2008-9-15 01:28:12 | 显示全部楼层
de存在就方便了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行