2013-10-24 32 views
5

Stavo scrivendo un programma che utilizza la funzione WM_CONCAT. Quando eseguo questa query:WM_CONCAT con clausola DISTINCT - Pacchetto compilato contro query standalone Edizione

SELECT WM_CONCAT(DISTINCT employee_id) 
FROM employee 
WHERE ROWNUM < 20; 

Funziona correttamente. Quando provo a compilare la relativamente stessa query in una funzione pacchetto o procedura, produce questo errore: PL/SQL: ORA-30482: l'opzione DISTINCT non consentita per questa funzione

FUNCTION fetch_raw_data_by_range 
RETURN VARCHAR2 IS 

    v_some_string VARCHAR2(32000); 

BEGIN 

    SELECT WM_CONCAT(DISTINCT employee_id) 
    INTO v_some_string 
    FROM employee 
    WHERE ROWNUM < 20; 

    RETURN v_some_string; 

END; 

mi rendo conto WM_CONCAT non è ufficialmente supportato ma qualcuno può spiegare perché avrebbe funzionato come query indipendente con DISTINCT, ma non in un pacchetto?

+1

Si dovrebbe essere in grado di ottenere simili risultati con la funzione LISTAGG. – OldProgrammer

+2

L'ho taggato come oracle10g, che non fornisce quella funzione – Reimius

risposta

5

Il problema è che WM_CONCAT è una stored procedure scritta in pl/sql.

C'è un bug aperto # 9323679: PL/SQL CHIAMARE UNA FUNZIONE AGGREGRATA DEFINITA DALL'UTENTE CON DISTINCT FAILS ORA-30482.

Soluzione alternativa per problemi come questo è l'utilizzo di SQL dinamico.

Quindi, se si avvolgono la query in

EXECUTE IMMEDIATE '<your_query>'; 

Poi dovrebbe funzionare.

Ma come già suggerito da OldProgrammer, è meglio evitare di utilizzare questo WM_CONCAT.

+0

Potete fornire un collegamento alla documentazione che descrive questo comportamento? – Reimius

+0

@Reimus Ci dispiace, sembra che io sia un po 'confuso con il nuovo comportamento di 11g. Sto correggendo questa risposta. – Nagh

+0

Ah, quindi è un bug e non a causa di alcuni requisiti funzionali. Grazie per il materiale di riferimento. Non ho accesso al loro tracker, ma sono riuscito a trovare più post relativi al numero di bug. – Reimius

3

PL/SQL non consente di utilizzare distinct in una funzione aggregata e questo problema mostra che il motore SQL e il motore PL/SQL non utilizzano lo stesso parser.

Una delle soluzioni a questo problema è quello di utilizzare sub domanda come sotto,

SELECT WM_CONCAT(employee_id) 
INTO v_some_string 
FROM (select DISTINCT employee_id 
     FROM employee) 
WHERE ROWNUM < 20; 

Un'altra soluzione è quella di utilizzare SQL dinamico come suggerito Nagh,

FUNCTION fetch_raw_data_by_range 
RETURN VARCHAR2 IS 

    v_some_string VARCHAR2(32000); 
    v_sql VARCHAR2(200); 

BEGIN 

    v_sql :='SELECT WM_CONCAT(DISTINCT employee_id) 
      FROM employee 
      WHERE ROWNUM < 20'; 

    execute immediate v_sql INTO v_some_string; 
    RETURN v_some_string; 
END; 
+0

Mi rendo conto che il parser pl/sql non è lo stesso del parser di query, ma quello che voglio veramente sapere è perché succede, cioè qual è la regola in atto che causa questo comportamento. È possibile che ci sia una buona ragione per cui DISTINCT non è ammesso in uno specifico scenario in pl/sql il cui esempio qui è un esempio di sottoinsieme e non rappresentativo del 'problema' nel suo complesso. – Reimius