oracle动态查询通过sql获取游标变量

Posted

技术标签:

【中文标题】oracle动态查询通过sql获取游标变量【英文标题】:oracle dynamic query fetch cursor variables through sql 【发布时间】:2014-07-08 15:24:30 【问题描述】:

需要一点帮助。我有一个动态查询,将 4 个列名和两个表名输出到 6 个游标变量中。现在我需要使用游标变量来选择前 4 列,然后使用游标变量从两个表名中选择,因为这些包含数据认为使用包含查询但我不知道的变量通过查询获取的东西如何去做。这就是我现在所拥有的,我只需要获取游标变量并将它们放入查询中

DECLARE
arow            VARCHAR2 (1000);

column1         VARCHAR2 (50);
column2         VARCHAR2 (50);
column3         VARCHAR2 (50);
column4         VARCHAR2 (50);
table1          VARCHAR2 (50);
table2          VARCHAR2 (50);
match           VARCHAR2 (50);
match1          VARCHAR2 (50);
sql_statement   VARCHAR2 (500);
BEGIN
FOR arow IN (SELECT   column_name_old,
                     column_name_new,
                     column_name_old_2,
                     column_name_new_2,
                     table_name_old,
                     table_name_new
              FROM   A550003.META_DATA_TABLE)
LOOP
  sql_statement :=
        'INSERT'
     || ' '
     || 'INTO'
     || ' '
     || 'a550003.MATCH_TABLE'
     || ' '
     || 'SELECT '
     || arow.column_name_old
     || ', '
     || arow.column_name_new
     || ', '
     || 'DECODE( '
     || arow.column_name_old
     || ', '
     || arow.column_name_new
     || ','
     || '1'
     || ','
     || '0)'
     || 'AS'
     || ' '
     || 'MATCH'
     || ','
     || arow.column_name_old_2
     || ', '
     || arow.column_name_new_2
     || ','
     || 'DECODE( '
     || arow.column_name_old_2
     || ', '
     || arow.column_name_new_2
     || ','
     || '1'
     || ','
     || '0)'
     || 'AS'
     || ' '
     || 'MATCH1'
     || ' FROM '
     ||' '
     || arow.table_name_old
     || ', '
     || arow.table_name_new
     || ' WHERE '
     || arow.column_name_old
     || '='
     || arow.column_name_new
     || '(+)';
  DBMS_OUTPUT.PUT_LINE (sql_statement);

 EXECUTE IMMEDIATE sql_statement;

  COMMIT;
END LOOP;
END;

【问题讨论】:

【参考方案1】:

首先你的 sql_statement 是错误的。您应该将此变量的值设置为这样的(当您将获得所有需要的名称时):

sql_statement := 'SELECT '
                 || column1 
                 || ', ' 
                 || column2 
                 || ', ' 
                 || column3 
                 || ', ' 
                 || column4 
                 || ' FROM ' 
                 || table1
                 || ', '
                 || table2
                 || ' WHERE '
                 || -- JOIN_CONDITION

然后你可以使用 EXECUTE IMMEDIATE 语句:

EXECUTE IMMEDIATE sql_statement
             INTO col1_val
                 ,col2_val
                 ,col3_val
                 ,col4_val
                 ;

当然变量 col[1..4]_val 必须声明。

还要注意 SQL 注入。

【讨论】:

嘿 kpater 感谢您的回复,对不起,我没有大量使用动态 sql。我已经编辑了我原来的帖子查询,我不知道它是否正确。我立即执行缺少的表达式,我不确定它是否应该从我的游标值中读取,因为它应该去哪里 1.在提出问题之前尝试格式化您的代码。 2. 您应该在从游标中获取数据后构建您的查询(设置 sql_statement 变量)。 3. 您的选择返回 4 列,因此您不应将 tab1_val 和 tab2_val 放入您的 INTO 部分 EXECUTE IMMEDIATE 语句中。 4. 如果您使用 INTO,那么您的选择应始终返回一条记录。如果您期望更多结果,您应该使用 BULK COLLECT INTO 和变量,这是一个集合。 我上面的代码可以编译,但实际上并没有插入到匹配表中 你一直在改变你的问题......之前没有关于向表中插入数据......我不知道你的数据,所以很难说为什么没有插入你的桌子。 正如@Wernfried 所写,使用DBMS_OUTPUT.PUT_LINE (sql_statement); 进行调试。你也可以把这个语句的一些输出放在问题中。【参考方案2】:

一定是这样的:

sql_statement := 'SELECT ' 
    || column1 || ', ' || column2 || ', ' || column3 || ', ' || column4 
    || ' FROM ' || table1 || ', ' || table2 
    || ' WHERE ' || column1 ||'=' ||column2||'(+)'; 
EXECUTE IMMEDIATE sql_statement INTO col1_val, col2_val, col3_val, col4_val;

或者最好

sql_statement := 'SELECT ' 
    || column1 || ', ' || column2 || ', ' || column3 || ', ' || column4 
    ||' FROM '||table1||' LEFT OUTER JOIN '||table2||' ON '||column1||'='||column2;
EXECUTE IMMEDIATE sql_statement INTO col1_val, col2_val, col3_val, col4_val;

对于调试DBMS_OUTPUT.PUT_LINE (sql_statement);会很有用!

那么你就不需要 Ref-Cursor,只需这样做:

BEGIN
   For aRow in (SELECT * FROM a550003.meta_data_table) LOOP
      sql_statement := 'SELECT '||aRow.column1||','||aRow.column2 ...
   END LOOP;
END;

【讨论】:

嘿 Wernfried 感谢您的帮助,看来这正是我所需要的。我让它工作了,现在如果我想让 sql_staement 写入一个表,我会在(对于 arow 部分)之前做一些类似于插入的事情,我现在还需要执行 sql_statement,就好像我只是把它放入一个编辑器选项卡并运行查询。现在我需要的查询在 DBMS 输出中,但现在我需要把它变成我可以实际运行的东西

以上是关于oracle动态查询通过sql获取游标变量的主要内容,如果未能解决你的问题,请参考以下文章

Oracle动态游标实现动态SQL循环遍历,和静态游标的比较。

如何提高Oracle中动态sql的查询性能

『ORACLE』 PLSQL动态游标的使用(11g)

oracle将查询的结果值作为下一个查询的字段列。

游标和动态SQL

Oracle 游标简介