的“完全成熟” dynmamic版本会是这样一个(未测试):
DECLARE
v_stmt_str VARCHAR2(200);
v_cur INTEGER;
v_rows_processed INTEGER;
col_cnt INTEGER;
rec_tab DBMS_SQL.DESC_TAB;
rec DBMS_SQL.DESC_REC;
num_var NUMBER;
string_var VARCHAR2(4000);
date_var DATE;
-- .. some more variables if needed
BEGIN
v_cur := DBMS_SQL.OPEN_CURSOR; -- open cursor
v_stmt_str := 'SELECT whatever from ....';
DBMS_SQL.PARSE(v_cur, v_stmt_str, DBMS_SQL.NATIVE);
DBMS_SQL.DESCRIBE_COLUMNS(v_cur, col_cnt, rec_tab);
FOR c in 1..col_cnt LOOP
rec := rec_tab(c);
IF rec.col_type = DBMS_TYPES.TYPECODE_NUMBER THEN
DBMS_SQL.DEFINE_COLUMN(v_cur, c, num_var);
ELSIF rec.col_type = DBMS_TYPES.TYPECODE_VARCHAR2 THEN
DBMS_SQL.DEFINE_COLUMN(v_cur, c, string_var, rec.col_max_len);
ELSIF rec.col_type = DBMS_TYPES.TYPECODE_DATE THEN
DBMS_SQL.DEFINE_COLUMN(v_cur, c, date_var);
-- .. some more data types if needed
END IF;
END LOOP;
-- Execute
v_rows_processed := DBMS_SQL.EXECUTE(v_cur);
LOOP
-- Fetch a row
IF DBMS_SQL.FETCH_ROWS(v_cur) > 0 THEN
FOR c in 1..col_cnt LOOP
rec := rec_tab(c);
IF rec.col_type = DBMS_TYPES.TYPECODE_NUMBER THEN
DBMS_SQL.COLUMN_VALUE(v_cur, c, num_var);
ELSIF rec.col_type = DBMS_TYPES.TYPECODE_VARCHAR2 THEN
DBMS_SQL.COLUMN_VALUE(v_cur, c, string_var);
ELSIF rec.col_type = DBMS_TYPES.TYPECODE_DATE THEN
DBMS_SQL.COLUMN_VALUE(v_cur, c, date_var);
-- .. some more data types if needed
END IF;
END LOOP;
-- Process: do something with num_var or string_var or date_var values
ELSE
EXIT;
END IF;
END LOOP;
DBMS_SQL.CLOSE_CURSOR(v_cur); -- close cursor
END;
/
但正如评论已经指出,检查你的要求,如果你真的需要它这种动态 - 大概不会。
查看Oracle文档Coding Dynamic SQL和DBMS_SQL获取其他示例。有各种方法提供不同的“动态水平”。
你现实可能不行。您可能能够动态地构建整个PL/SQL块(包括后续循环),但诉诸动态PL/SQL通常是快速驱动自己(以及任何需要维护代码的人)的疯狂方式。您可能希望使用'dbms_sql'而不是'immediate immediate',但您真的很想编写通用的代码非常罕见。你试图解决的根本问题是什么? – 2014-10-10 18:07:49
感谢您的快速响应!我想构建一个函数来获取表的名称和它的一个PK值,然后删除子表中的所有相应行,以及子表的子元素等等。我不能用级联来改变我的桌子。 – Dax 2014-10-10 18:15:38
你确定你确实需要一个完全通用的函数吗?而不是说,一个'delete_foo'过程通过首先从所有属于'foo'子元素的表中删除数据来删除'foo'?您可以构建一个从一堆数据字典表中读取的单个过程,并创建一堆动态SQL。但这比一个简单的程序选项复杂得多。你确定额外的复杂性真的值得吗? – 2014-10-10 18:40:52