2014-10-10 48 views
0

在以下查询中,select_string可以返回任意数量的具有任何可能数据类型的列和行。如何动态创建一个具有表格数据类型的变量?

Execute immediate 'select_string' into v_table_variable; 

例如select_string可以'select name, last name from student''select date, subject, address , phone from booking'等。

有没有人有任何想法如何我可以定义v_table_variable,以便执行立即运行,因为我想??我打算在之后做一个循环来读取这个变量的值。

非常感谢!

+1

你现实可能不行。您可能能够动态地构建整个PL/SQL块(包括后续循环),但诉诸动态PL/SQL通常是快速驱动自己(以及任何需要维护代码的人)的疯狂方式。您可能希望使用'dbms_sql'而不是'immediate immediate',但您真的很想编写通用的代码非常罕见。你试图解决的根本问题是什么? – 2014-10-10 18:07:49

+0

感谢您的快速响应!我想构建一个函数来获取表的名称和它的一个PK值,然后删除子表中的所有相应行,以及子表的子元素等等。我不能用级联来改变我的桌子。 – Dax 2014-10-10 18:15:38

+0

你确定你确实需要一个完全通用的函数吗?而不是说,一个'delete_foo'过程通过首先从所有属于'foo'子元素的表中删除数据来删除'foo'?您可以构建一个从一堆数据字典表中读取的单个过程,并创建一堆动态SQL。但这比一个简单的程序选项复杂得多。你确定额外的复杂性真的值得吗? – 2014-10-10 18:40:52

回答

2

的“完全成熟” 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 SQLDBMS_SQL获取其他示例。有各种方法提供不同的“动态水平”。

+0

谢谢你的提示:-)。我对DBMS_SQL不熟悉。只有一件事,不应该“用num_var或...做些什么”在最后的循环之前?如果我们的查询返回例如带有数据类型编号的4列,那么我想,这样我们只会有num_var中的最后一个值,对吧?!只是想确保我已经做对了。这对我很有帮助,非常感谢你:-) – Dax 2014-10-11 12:16:42

+0

YEs,如果你的表包含多个'NUMBER'类型的列,你必须在循环内处理它们。或者,您可以将它们放入嵌套表格中,并在循环后处理嵌套表格。 – 2014-10-11 12:59:41

相关问题