将列名从一个游标传递到另一个游标的 select 语句

Passing column name from one cursor to select statement of another cursor

我有两个游标 c11 和 c2。我有两个 tables compare1 和 compare2.Both 具有相同的列但值不同。我想将 c1 的结果传递给 c2 游标。我正在从 user_tab_columns 中获取 table 的列名称。我想传递列名以获取比较 1 和比较 2 tables 之间唯一记录的差异。但是 c1 中的列名没有传递给 c2.Please 找到我试过的代码。

DECLARE
   COL         VARCHAR2 (200);
  OUTRECORD   VARCHAR2 (200);
   CURSOR c1  IS
  SELECT COLUMN_NAME
    FROM all_tab_columns
   WHERE     table_name = 'COMPARE1';            
CURSOR c2( col varchar(200))   IS--col is the column names from c1 
   (SELECT DISTINCT COL
            FROM COMPARE1
          MINUS
          SELECT DISTINCT COL
            FROM COMPARE2);
BEGIN
  OPEN c1;
  LOOP
    FETCH c1 INTO COL;
    DBMS_OUTPUT.put_line (COL);
    OPEN c2(col);--col Is not passing to 2nd cursor
    LOOP
      FETCH c2 INTO OUTRECORD;--outrecord is empty is col is not passed to 2nd cursor
      INSERT INTO RESULT
          VALUES ('B001',
                  'COMPARE',
                  '2018',
                  COL,
                  OUTRECORD,--empy value
                  'NOT PRESENT IN 2017');
      COMMIT;
    END LOOP;
    CLOSE c2;
  END LOOP;
  CLOSE c1;
END;

帮我提前传值给c1.Thanks

您的代码未按预期运行的主要原因是您将第一个游标的列名称作为文字值传递到第二个游标。

因此,当您在第二个游标中执行减号操作时,您是在比较一个字符串是否与该字符串相同,这意味着不会返回任何行。 IE。它本质上是:

select 'x' from some_table
minus
select 'x' from some_other_table;

要解决这个问题,您需要使用动态 sql - 下面是一个使用游标和引用游标的示例:

DECLARE
  rc        SYS_REFCURSOR;
  outrecord VARCHAR2(200);
BEGIN
  FOR r1 IN (SELECT column_name col
             FROM   all_tab_columns
             WHERE  table_name = 'COMPARE1')
  LOOP
    dbms_output.put_line(r1.col);

    OPEN rc FOR 'SELECT '||r1.col||' col'||CHR(10)||
                'FROM   compare1'||CHR(10)||
                'MINUS'||CHR(10)||
                'SELECT '||r1.col||' col'||CHR(10)||
                'FROM   compare2';

    LOOP
      FETCH rc
        INTO outrecord; 

      EXIT WHEN rc%NOTFOUND;

      INSERT INTO RESULT -- you should list the columns being inserted into here
      VALUES
        ('B001',
         'COMPARE',
         '2018',
         r1.col,
         outrecord,
         'NOT PRESENT IN 2017');
      COMMIT;
    END LOOP;
  END LOOP;

  CLOSE rc;
END;
/

您可以看到我已经将围绕第一个游标的循环转换为游标循环,而不是显式获取每一行。这样,您就不必担心检查是否已到达行尾或关闭游标。通过我在缺少的 exit when rc%notfound 子句中添加的第二个游标的内部循环。

另请注意,我已从您的减号查询中删除了 distincts - minus 已经区分了行,因此无需明确说明。

但是,您要做的是逐行插入,这根本不是最佳方法 - 您应该在单个插入语句中完成所有工作,您可以看到下面:

BEGIN
  FOR r1 IN (SELECT column_name col
             FROM   all_tab_columns
             WHERE  table_name = 'COMPARE1')
  LOOP
    dbms_output.put_line(r1.col);

    execute immediate 'INSERT INTO RESULT'||CHR(10)|| -- you should list the columns being inserted into here
                      'SELECT ''B001'','||CHR(10)||
                      '       ''COMPARE'','||CHR(10)||
                      '       ''2018'','||CHR(10)||
                      '       '''||r1.col||''','||CHR(10)||
                      '       '||r1.col||CHR(10)||
                      'FROM   compare1'||CHR(10)||
                      'MINUS'||CHR(10)||
                      'SELECT ''B001'','||CHR(10)||
                      '       ''COMPARE'','||CHR(10)||
                      '       ''2018'','||CHR(10)||
                      '       '''||r1.col||''','||CHR(10)||
                      '       '||r1.col||CHR(10)||
                      'FROM   compare2';

  END LOOP;    END;
/

N.B。未经测试。