2017-04-26 40 views
0

我有麻煩排序嵌套表進行排序基於一些動態信息,這將是在order by子句中嵌套表。基於動態信息

這裏是什麼,我已經找到(https://technology.amis.nl/2006/05/31/sorting-plsql-collections-the-quite-simple-way-part-two-have-the-sql-engine-do-the-heavy-lifting/

樣本這裏唯一的不同是,我需要通過條款動態定義的順序列和方向

SELECT CAST(MULTISET(SELECT * 
         FROM TABLE(table_a) 
         ORDER BY P_SORT_COLUMN P_DIRECTION 
        ) as table_typ) 
    INTO table_b 
    FROM dual; 

因此得到解決認爲我想使用動態SQL,並把它放在一個進程的形式不能做到這一點動態

loc_sql_stmt VARCHAR2(500); 



BEGIN 

    loc_sql_stmt := 'SELECT CAST(MULTISET(SELECT * ' || 
              'FROM TABLE(P_TABLE_A) ' || 
              'ORDER BY P_COLUMN P_DIRECTION ||) as table_typ) ' || 
          'INTO P_TABLE_B' || 
          'FROM dual;'; 


    EXECUTE IMMEDIATE loc_sql_stmt 
      USING IN P_TABLE_A, P_COLUMN, P_DIRECTION, P_TABLE_B; 

END; 

有錯誤我從EXECUTE IMME得到DIATE線是「ORA-00936缺少表達式

那麼有沒有更好的方法來按任何給定的列和方向排序一個嵌套表,或者如何讓這個動態SQL工作?

這裏有一個例子:

在DB創建此:

CREATE OR REPLACE TYPE table_obj AS OBJECT(
        column1  VARCHAR2(20), 
        column2  VARCHAR2(20)); 

    CREATE OR REPLACE TYPE table_typ AS TABLE OF table_obj; 

,然後運行示例:

DECLARE 
    table_a   table_typ := table_typ(); 
    table_b   table_typ := table_typ(); 
    loc_idx   NUMBER; 
    loc_sort_column INTEGER := 1; 
    loc_desc   VARCHAR2 (4); 
    P_SORT_COLUMN  VARCHAR2 (100) := 'column1'; 
    P_DIRECTION  VARCHAR2 (4) := 'DESC'; 
    loc_sql_stmt  VARCHAR2 (500); 
BEGIN 
    FOR i IN 1 .. 5 
    LOOP 
     loc_idx := table_a.COUNT + 1; 
     table_a.EXTEND; 
     table_a (loc_idx) := table_obj (NULL, NULL); 

     table_a (loc_idx).column1 := TO_CHAR (loc_idx); 
     table_a (loc_idx).column2 := TO_CHAR (loc_idx); 
    END LOOP; 

    -- 
    loc_sql_stmt := 
    'SELECT CAST(MULTISET(SELECT * ' || 
          'FROM TABLE(' || table_a || ') ' || 
          'ORDER BY ' || P_SORT_COLUMN || ' '|| P_DIRECTION || 
         ') as table_typ) ' || 
     'INTO :table_b' || 
     'FROM dual'; 

    EXECUTE IMMEDIATE loc_sql_stmt USING IN OUT table_a, table_b; 

FOR i IN 1 .. table_b.COUNT 
LOOP 
    DBMS_OUTPUT.PUT_LINE (table_b (i).rx_number); 
END LOOP; 
END; 

回答

1

爲參數名前通過變量本地動態SQL使用:,建立動態語句中使用串聯,這樣

loc_sql_stmt VARCHAR2(500); 

BEGIN 

    loc_sql_stmt := 'SELECT CAST(MULTISET(SELECT * ' || 
              'FROM TABLE('|| P_TABLE_A || ') ' || 
              'ORDER BY ' || P_COLUMN || ', ' || P_DIRECTION || ') as table_typ) ' || 
          'INTO :P_TABLE_B' || 
          'FROM dual;'; 


    EXECUTE IMMEDIATE loc_sql_stmt 
      USING OUT P_TABLE_B; 
END; 

編輯後的版本:

現在看到你的代碼,我理解你的需求。爲了使它的工作,我們需要使用動態PL/SQL塊,而不是本地SQL這裏工作的示例代碼,並注意什麼是可變的,什麼是串接字面

DECLARE 
    table_a table_typ := table_typ(); 
    table_b table_typ := table_typ(); 
    loc_idx NUMBER; 
    loc_sort_column INTEGER := 1; 
    loc_desc VARCHAR2(4); 
    P_SORT_COLUMN VARCHAR2(100) := 'column1'; 
    P_DIRECTION VARCHAR2(4) := 'desc'; 
    loc_sql_stmt VARCHAR2(500); 
BEGIN 
    FOR i IN 1 .. 5 
    LOOP 
     loc_idx := table_a.COUNT + 1; 
     table_a.EXTEND; 
     table_a(loc_idx) := table_obj(NULL, NULL); 

     table_a(loc_idx).column1 := TO_CHAR(loc_idx); 
     table_a(loc_idx).column2 := TO_CHAR(loc_idx); 
    END LOOP; 

    -- 
    loc_sql_stmt := 'begin SELECT CAST(MULTISET(SELECT * ' || 
        'FROM TABLE(:table_a) ORDER BY ' || P_SORT_COLUMN || ' ' || 
        P_DIRECTION || ') as table_typ) ' || ' INTO :table_b ' || 
        'FROM dual; end;'; 

    EXECUTE IMMEDIATE loc_sql_stmt 
     USING table_a, IN OUT table_b; 

    FOR i IN 1 .. table_b.COUNT 
    LOOP 
     DBMS_OUTPUT.PUT_LINE(table_b(i).column1); 
    END LOOP; 
END; 
+0

我想我已經嘗試了這一點太多,但得到以下 ORA-06550:行72,列27: PLS-00306:錯號碼或類型的調用參數「||」 – programmerNOOB

+0

對不起,但第72行第27列沒有對我說什麼,我沒有看到你的真實代碼與真正的參數值,如果你提供一些數據和結構,它會更容易找到解決方案。 – Seyran

+0

我添加上述 – programmerNOOB

0

如果有限列/方向選擇,嘗試的情況下,在您的訂單聲明,簡單的例子:

select * from tab 
order by case when :order = 'c1_asc' then c1 else null end asc 
     , case when :order = 'c1_desc' then c1 else null end desc 
     , case when :order = 'c2_asc' then c2 else null end asc 
     , case when :order = 'c2_desc' then c2 else null end desc 
/* ... */ 
; 
+0

我一直在使用的情況下,試圖/解碼和由於某種原因,因爲該值不是一個靜態1,columnA等....它不接受返回值的大小寫/解碼 – programmerNOOB

+0

好吧,對不起;我知道這是可以做到的,因爲我一直通過TOAD來完成,只需要:標識符和TOAD進行替換。 –