2017-03-20 50 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

相關問題