2015-04-17 108 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