2017-03-20 22 views
0

我有两个游标c11和c2。我有两个表compare1和compare2.Both具有相同的列但值不同。我想将c1的结果传递给c2游标。我正在从user_tab_columns获取表的列名。我想传递列名以获取比较1和比较2表之间唯一记录的差异。但是来自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提前

+0

哪个RDBMS是为了这个?无论您使用的是MySQL,PostgreSQL,Oracle,SQL Server还是IBM DB2,或者甚至是其他软件,它都会产生影响。请为您的问题添加相关标签! –

+0

我们正在使用Oracle – mano

回答

2

的最主要的原因,因为你希望它你的代码不工作是因为你从第一光标通过列名成第二个游标作为文字值。

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

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

要解决这个问题,就需要使用动态SQL - 这里是一个使用游标和REF CURSOR的例子:

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子句中。

请注意,我已经从您的减号查询中删除了distinct - 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; 
/

NB未经测试。

+0

非常感谢答案:)。现在我明白了。但是我得到的标识符是select语句的错误太长了。有什么办法摆脱它 – mano

+0

道歉;我错过了我最后的pl/sql块中的'execute immediate'。至于你得到的错误信息,你可能会发现你的列有别于你的帮助。 ''SELECT''B001'','|| CHR(10)||'变成''SELECT''B001''some_alias_name,'|| CHR(10)|| – Boneist

+0

对于第一个解决方案,如果我尝试使用别名,我得到错误说'预计会使用' – mano

相关问题