PLSQL动态查询

时间:2015-04-17 05:56:44

标签: oracle plsql dynamic-sql

我有一个表A,其列A将表名保存为值。 所有这些表都有一个共同的列C。我需要每个表的此列的最大值。

我使用动态SQL尝试了这个,但我遇到了错误。请建议。

DECLARE    
 query1 VARCHAR2(100);
 c_table VARCHAR2(40);
 c_obj VARCHAR2(20);
 Cursor cursor_a IS
 SELECT a FROM A;  
BEGIN
Open cursor_a;
   LOOP
      Fetch cursor_a INTO c_table2;      
      EXIT WHEN cursor_a%notfound;     
      query1 := 'SELECT max(object_ref) AS "c_obj" FROM c_table' ;
      EXECUTE IMMEDIATE query1;
      dbms_output.put_line('Maximum value: '|| c_table || c_obj);
   END LOOP;
Close cursor_a;
END;

2 个答案:

答案 0 :(得分:2)

动态SQL无法看到您的PL / SQL变量:您需要传递一个字符串,该字符串可以在SQL引擎的范围内执行。因此,您需要将表名与语句的样板文本连接起来:

query1 := 'SELECT max(c)  FROM ' || variable_name;

您还需要将查询结果返回到变量中。

以下是它的工作原理(我已从您的示例中删除了一些不必要的代码):

DECLARE    
 c_table VARCHAR2(40);
 c_obj VARCHAR2(20);
BEGIN
   for lrec in ( select a as tab_name from A )
   LOOP
      EXECUTE IMMEDIATE 'SELECT max(object_ref)  FROM ' || lrec.tab_name 
           into c_obj ;
      dbms_output.put_line('Maximum value: '|| lrec.tab_name
           || '='|| c_obj);
   END LOOP;
END;

答案 1 :(得分:-4)

您使用的变量中存在一些未匹配,即

  1. 声明为" c_table "但访问" c_table2 "
  2. 每个表的常用列名是" C "但访问" object_ref "
  3. 在动态查询中,使用 INTO 关键字将值存储到您的varibale
  4. <强>建议

    1. 使用concat()函数动态准备查询,例如:

      SET @SQL:= CONCAT(&#39; SELECT max(c)INTO&#39;,c_obj,&#39; FROM&#39;,c_table);

    2. 实施动态查询的步骤是:

      SET @SQL = <your dynamic query>
      PREPARE stmt FROM @SQL;
      EXECUTE stmt;
      
    3. 示例代码:

      DECLARE    
       query1 VARCHAR2(100);
       c_table VARCHAR2(40);
       c_obj VARCHAR2(20);
       CURSOR cursor_a IS
       SELECT a FROM A;  
      BEGIN
      OPEN cursor_a;
         LOOP
            FETCH cursor_a INTO c_table;      
            EXIT WHEN cursor_a%notfound; 
            SET @SQL := CONCAT('SELECT max(object_ref) AS c_obj INTO ', c_obj, ' FROM ',c_table);
          PREPARE stmt FROM @SQL;         
          EXECUTE stmt;    
          dbms_output.put_line('Maximum value: '|| c_table || c_obj);
         END LOOP;
      CLOSE cursor_a;
      END;