2015-04-17 121 views
-1

我在這裏做錯了什麼?我想要這個SQL查詢在一個過程FOR i列中執行。我在拼接錯誤嗎?謝謝!將SQL查詢轉換爲PL/SQL

BEGIN 
FOR i IN 1..NR_COLUMNS 
LOOP 
EXECUTE IMMEDIATE 'select * from (
    select id, c, row_number() over (partition by id 
     order by id, decode(mod(id, 2), 1, c, -c)) rn 
     from FIRST_TABLE unpivot (c for col in (col'||i||'))) 
    pivot (max(c) for rn in (i as col'||i||'))'; 
END LOOP; 

錯誤:ORA-56901:非恆定表達不允許樞軸|逆透視值 ORA-06512:在第4行 56901. 0000 - 「非恆定表達不允許樞軸|逆透視值「 *原因:嘗試對pivot | unpivot值使用非常量表達式。 *操作:使用pivot | unpivot值的常量。

+0

請提供一些關於您遇到的問題或錯誤以幫助您瞭解問題的詳細信息。 – Drenmi

+0

@Drenmi我更新了代碼。請看看 – XhensB

+0

可能的重複[轉換查詢從SQL到PL/SQL](http://stackoverflow.com/questions/29688456/convert-query-from-sql-to-pl-sql) – user272735

回答

1

你可以做這個例子。首先創建與您的表相同列的空表。

create table sorted as select * from first_table where 1=0; 

現在你可以運行這個代碼塊(你可以把它放在程序或其他東西中)。 它填寫表sorted與您想要的順序排列的值。

declare 
    v_list1 varchar2(32000); v_list2 varchar2(32000); 
    v_sql varchar2(32000); v_num number; v_rec first_table%rowtype; 
begin 

    select count(1) into v_num from user_tab_cols 
    where table_name = 'FIRST_TABLE'; 

    for i in 1..v_num-1 loop 
    v_list1 := v_list1||'col'||i||', '; 
    v_list2 := v_list2||i||', '; 
    end loop; 

    v_sql := 'select * from (
     select id, c, row_number() over (partition by id 
      order by id, decode(mod(id, 2), 1, c, -c)) rn 
     from first_table unpivot (c for col in ('||rtrim(v_list1, ', ')||'))) 
    pivot (max(c) for rn in ('||rtrim(v_list2, ', ')||'))'; 

    for r in (select * from first_table) loop 
    execute immediate v_sql||' where id = '||r.id into v_rec; 
    insert into sorted values v_rec; 
    end loop; 
end; 

這裏是塊不使用其他表,分類變量v_coll數據收集 ,那麼舊數據從first_table和新插入的去除。

declare 
    v_list varchar2(32000); v_sql varchar2(32000); v_num number; 
    type tft is table of first_table%rowtype; 
    v_coll tft; -- variable for sorted data collection 
begin 

    select count(1) into v_num from user_tab_cols where table_name = 'FIRST_TABLE'; 

    for i in 1..v_num-1 loop 
    v_sql := v_sql||'col'||i||', '; 
    v_list := v_list||i||', '; 
    end loop; 

    v_sql := 'select * from (
     select id, c, row_number() over (partition by id 
      order by id, decode(mod(id, 2), 1, c, -c)) rn 
     from first_table unpivot (c for col in ('||rtrim(v_sql, ', ')||'))) 
    pivot (max(c) for rn in ('||rtrim(v_list, ', ')||'))'; 

    -- execute statement and collect sorted data in v_coll 
    execute immediate v_sql bulk collect into v_coll; 

    delete from first_table; 
    forall i in 1..v_coll.count 
    insert into first_table values v_coll(i); 

end; 
+0

非常感謝您的幫助。我標記爲已回答。它完美的作品。 – XhensB

1

眼前的問題是,你指的是i的動態語句中的變量,它是不是在範圍:

pivot (max(c) for rn in (i as col'||i||'))'; 
         ^

您需要連接,當你擁有了日後參考:

pivot (max(c) for rn in ('||i||' as col'||i||'))'; 

那現在編譯,但@jva提到自己不選擇做任何事所以沒什麼的結果發生(事實上the query isn't actually executed)。儘管你想和他們做什麼並不明顯。

它看起來像你試圖建立樞軸/ unpivot子句,而不是你實際在做什麼,它試圖運行查詢多個不相關的時間。我認爲這可能是更接近你想達到什麼目的:

DECLARE 
    NR_COLUMNS NUMBER := 2; 
    QUERY VARCHAR2(1000); 
BEGIN 
    QUERY := 'select * from (
    select id, c, row_number() over (partition by id 
     order by id, decode(mod(id, 2), 1, c, -c)) rn 
     from FIRST_TABLE unpivot (c for col in ('; 

    FOR i IN 1..NR_COLUMNS 
    LOOP 
    IF i > 1 THEN 
     QUERY := QUERY || ', '; 
    END IF; 
    QUERY := QUERY || 'col' ||i; 
    END LOOP; 

    QUERY := QUERY || '))) 
    pivot (max(c) for rn in ('; 

    FOR i IN 1..NR_COLUMNS 
    LOOP 
    IF i > 1 THEN 
     QUERY := QUERY || ', '; 
    END IF; 
    QUERY := QUERY || i ||' as col' ||i; 
    END LOOP; 
    QUERY := QUERY || '))'; 

    -- just to debug what you're trying to run 
    DBMS_OUTPUT.PUT_LINE(QUERY); 
    EXECUTE IMMEDIATE QUERY; 
END; 
/

的DBMS_OUTPUT顯示等產生的查詢:

select * from (
    select id, c, row_number() over (partition by id 
     order by id, decode(mod(id, 2), 1, c, -c)) rn 
     from FIRST_TABLE unpivot (c for col in (col1, col2))) 
    pivot (max(c) for rn in (1 as col1, 2 as col2)) 

但它仍然不會實際做任何事情。您需要選擇某個東西(一個集合),或者使用生成的查詢打開一個遊標並遍歷結果,或者返回一個引用遊標或其他東西。目前還不清楚你想要發生什麼。

+0

非常感謝您的回答。 我想要做的就是更新現有的表格,但我爲此付出了很多努力。 – XhensB