2017-04-26 2 views
0

Ich habe Probleme beim Sortieren einer geschachtelten Tabelle basierend auf einigen dynamischen Informationen, die in der Reihenfolge nach Klausel sein würde. HierSortieren geschachtelte Tabelle basierend auf dynamischen Informationen

ist eine Probe von dem, was ich gefunden habe (https://technology.amis.nl/2006/05/31/sorting-plsql-collections-the-quite-simple-way-part-two-have-the-sql-engine-do-the-heavy-lifting/)

Der einzige Unterschied hier ist, ich brauche, um dynamisch die Spalte und Richtung in der Reihenfolge zu definieren, indem Klausel

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

So zu umgehen ich denke daran gedacht, mit dynamischem SQL und steckt es in einer proc als Formen diesen dynamisch nicht tun können

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; 

irrtümlicher ich von der EXECUTE IMME erhalten DIATE Zeile ist "ORA-00936 fehlenden Ausdruck

So gibt es eine bessere Möglichkeit zum Sortieren einer Neset-Tabelle durch eine beliebige Spalte und die Richtung oder wie bekomme ich diese dynamische SQL zu arbeiten? Hier

ist ein Beispiel:

schaffen dies in 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; 

und dann ein Probelauf:

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; 

Antwort

1

Um Variable zu nativem dynamischen SQL Verwendung : vor Parameternamen übergeben, dynamische Anweisung Verwendung Verkettung zu bauen, wie diese

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; 

editierte Version:

Jetzt Ihren Code zu sehen, ich verstehe, was Sie brauchen. Um es machen wir arbeiten müssen dynamische PL/SQL-Block verwenden, nicht Native SQL ist hier Code Ihrer Probe zu arbeiten und darauf achten, was variabel ist und was verketteten wörtliche

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

Ich denke, ich habe das auch ausprobiert, aber bekomme folgende ORA-06550: Zeile 72, Spalte 27: PLS-00306: falsche Anzahl oder Arten von Argumenten im Aufruf von '||' – programmerNOOB

+0

Sorry, aber Zeile 72 Spalte 27 sagt nichts zu mir, ich sehe nicht Ihren realen Code mit echten Param-Werten, wenn Sie einige Daten und Struktur bereitstellen, wird es viel einfacher, Lösung zu finden. – Seyran

+0

Ich habe ein Beispiel hinzugefügt über – programmerNOOB

0

Wenn Sie Spalte/Richtung Auswahl begrenzt haben, versuchen Sie einen Fall Anweisung in Ihrer Bestellung durch, einfaches Beispiel:

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

habe ich versucht, einen Fall mit/dekodieren und aus irgendeinem Grund, weil der Wert keine statische 1, columnA usw. ist .... es akzeptiert nicht den Wert, der aus dem Fall zurückgegeben wird/decode – programmerNOOB

+0

ok, Sorry; Ich weiß, dass es getan werden kann, weil ich es die ganze Zeit durch TOAD mache, nur mit: Bezeichner und TOAD macht die Ersetzung. –

Verwandte Themen