2017-01-13 1 views
2

Ich muss eine Abfrage schreiben, die unten tut. Ich habe es versucht, konnte aber nicht schreiben. Bitte hilf mir.Brauchen Sie Hilfe beim Schreiben von SQL-Abfrage mit dynamischen Spalten

Ich habe Tabelle, die unter Ergebnismenge zurückgibt.

select * 
from table1; --(rowid and ColumnName are columns of the table) 

Ausgang:

rowid  ColumnName 
------------------------------ 
    1  Segment1  
    2  Segment2 

Ich habe eine andere Tabelle, die unten folgende Struktur aufweist: (Segment1 und Segment2 sind Spalten hier)

select * 
from table2; 

Ausgang:

appId  Segment1  Segment2  Segment3 
--------------------------------------------- 
    a1  fld1   fld2   per 
    a2  cmp1   hcd4   klp 

I muss eine Abfrage schreiben, die h liest die Werte von "ColumnName" aus der ersten Tabelle und ruft Spaltenwerte in der zweiten Tabelle ab.

Das heißt, aus der Tabelle1, ich werde wissen, was die verfügbaren Spalten I die Tabelle2 und aus Tabelle2, werde ich wissen, was ist die Daten gegen diese Spalten gespeichert.

Bitte lassen Sie mich wissen, wenn ich nicht klar bin. Diese Abfrage ist in Oracle SQL

+0

Was ist die Abfrage an die erste Tabelle .. i.e Auf welcher Basis wählen Sie, ob die Ausgabe aus Tabelle 1 Segment1 oder Segment2 ist? –

+0

Ich muss alle ColumnName-Werte in der Tabelle1 lesen und ihre Werte aus der Tabelle2 abrufen. – Anveshan

+0

Die Werte aus der Spalte "ColumnName" aus Tabelle1 sollten mit den Spaltennamen in Tabelle 2 gemappt werden und sollten die Werte – Anveshan

Antwort

1

Wie im Kommentar Sie PLSQL Block mit dynamischem SQL müssen erwähnt . Im folgenden sehen Sie ein Beispiel:

Tables:

create table table1 (row_id number, 
        ColumnName varchar2(100)) 

create table table2 (appId  number, 
        Segment1 varchar2(100), 
        Segment2 varchar2(100),  
        Segment3 varchar2(100)); 

Insert all 
    into TABLE1 (ROW_ID, COLUMNNAME) Values (1, 'Segment1') 
    into TABLE1 (ROW_ID, COLUMNNAME) Values (2, 'Segment2') 
    into TABLE2 (APPID, SEGMENT1, SEGMENT2, SEGMENT3) Values (1, 'RRR', 'KKK', 'MMM') 
    into TABLE2 (APPID, SEGMENT1, SEGMENT2, SEGMENT3) Values (2, 'ZZZ', 'PPP', 'QQQ') 
    into TABLE2 (APPID, SEGMENT1, SEGMENT2, SEGMENT3) Values (3, 'LLL', 'NNN', 'DDD') 
select * from dual; 

Code:

DECLARE 
    var  VARCHAR2 (1000); 
    v_sql VARCHAR2 (2000); 
    TYPE x_var IS TABLE OF VARCHAR2(1000); 
    z_var x_var; 
    num number:=0; 
BEGIN 
    FOR rec IN ( SELECT DISTINCT columnname 
        FROM table1 
        ORDER BY 1) 
    LOOP   
     num := num +1;  
     if num = 1 then 
     var:= rec.columnname;  
     else 
     var := var || ' || '' , ''||' || rec.columnname; 
     end if; 

    END LOOP; 

    var := RTRIM (LTRIM (var, ','), ','); 

    v_sql := 'select '|| var ||' from table2';  

    EXECUTE IMMEDIATE v_sql BULK COLLECT INTO z_var; 

    FOR i IN 1 .. z_var.COUNT 
    LOOP 
     DBMS_OUTPUT.put_line (z_var(i)); 
    END LOOP; 
END; 

Ausgang:

SQL>/
RRR , KKK 
ZZZ , PPP 
LLL , NNN 
0

Wird der folgende PL SQL-Block Ihre Anforderung unterstützen.

BEGIN 
FOR iter IN (
       SELECT column_name 
       FROM all_tab_columns 
       WHERE upper(table_name) = 'table1' 
       AND UPPER(column_name) LIKE 'SEGMENT%' 
      )  
     LOOP 
      SELECT iter.column_name INTO temp_table FROM table1 
      dbms_output.put_line(temp_table.column_name); 
     END LOOP; 
END; 
/
+0

Eine kleine Beschreibung in Ihrer Antwort, die beschreibt, wie die von Ihnen zur Verfügung gestellte SQL funktioniert, wäre großartig. – Tom

+0

Dies funktioniert nicht; Hast du es versucht? – Aleksej

0

Angenommen, Sie haben Tabellen wie folgt aus:

SQL> select * from someTable; 

    COLUMN1 COLUMN2 COLUMN3 
---------- ---------- ---------- 
     1   2   3 
     2   4   6 
     3   6   9 

SQL> select * from tableOfColumns; 

COLUMNN 
------- 
column1 
column3 

Sie so etwas wie die folgenden benötigen:

SQL> declare 
    2  type tListOfResults is table of varchar2(1000); 
    3  vSQL varchar2(1000); 
    4  vResult tListOfResults ; 
    5 begin 
    6  select 'select ' || listagg (columnName, ' || '', '' || ') within group (order by columnName) || ' from someTable' 
    7  into vSQL 
    8  from tableOfColumns; 
    9  -- 
10  execute immediate vSQL bulk collect into vResult; 
11  if vResult.count() > 0 then 
12   for i in vResult.first .. vResult.last loop 
13    dbms_output.put_line(vResult(i)); 
14   end loop; 
15  end if; 
16 end; 
17/
1, 3 
2, 6 
3, 9 

PL/SQL procedure successfully completed. 
+0

Ich sehe Syntaxfehler im obigen Skript. "Teilweise anerkannte Regeln (Eisenbahndiagramme): .. – Anveshan

+0

Dieser Fehler scheint mit dem Oracle-Code nichts zu tun zu haben, wie hast du ihn ausgeführt? Ad was ist die komplette Fehlermeldung? – Aleksej

1

Dynamische Spalten in einer SQL-Anweisung sind fast immer eine schlechte Idee. Es gibt normalerweise eine Möglichkeit, diese Art von Problemen zu vermeiden und eine einfachere Lösung zu erstellen.

Aber wenn dies einer der seltenen Zeiten, in denen Sie wirklich Notwendigkeit dynamische SQL in SQL läuft dann müssen Sie installieren und Method4 so etwas wie mein Open-Source-Projekt.

Zum Beispiel:

create table table1 as 
select 1 id, 'Segment1' columnName from dual union all 
select 2 id, 'Segment2' columnName from dual; 

create table table2 as 
select 'a1' appId, 'fld1' Segment1, 'fld2' Segment2, 'per' Segment3 from dual union all 
select 'a2' appId, 'cmp1' Segment1, 'hcd4' Segment2, 'klp' Segment3 from dual; 

select * from table(method4.dynamic_query(
    q'[ 
     select 
       'select appID, ' 
      ||listagg(columnName, ',') within group (order by id) 
      ||' from table2' 
      sql_statement 
     from table1 
    ]' 
)); 

APPID SEGMENT1 SEGMENT2 
----- -------- -------- 
a1  fld1  fld2 
a2  cmp1  hcd4 

Es gibt so viele Nachteile zu laufen. Der Code ist kompliziert, langsam und hat ein merkwürdiges Verhalten. Für eine Erklärung, wie dies funktioniert, siehe this article von Adrian Billington.

Verwandte Themen