2012-11-21 22 views
8

È una mia costante frustrazione che Oracle PL/SQL supporti il ​​tipo di dati bool, mentre Oracle SQL no. È un grosso problema proverbiale quando si desidera elaborare un valore di ritorno booleano PL/SQL nel proprio SQL quotidiano (esempio sotto).Supporto Bool Oracle SQL

Anche il sito ask-Tom è blasé su questo disadattato, riferendo che si dovrebbe codificare colonne booleane come valori fissi 'Y'/'N' CHAR colonne, che è un esempio di cattivo risposta poliziotto-out su così tanti livelli diversi che non ho sapere da dove iniziare a criticarlo. In effetti, l'unica qualità di riscatto di questa risposta è il fatto che (per quanto ho scoperto di recente), molti altri motori di database non supportano neanche il tipo di dati booleani.

In ogni caso - la questione ...

Ho un work-around per il seguente problema (anche se disordinato e verbose), quindi sto facendo questa domanda per curiosità, piuttosto che per necessità. Ma una delle poche cose che mi sorprende di più è l'ingegno di programmatori intelligenti, quindi spero che uno di voi possa trovare una soluzione a quanto segue.

Nel seguente esempio, la funzione stock_pkg.is_in_stock() (che è parte integrante della mia applicazione) restituisce un valore booleano, rendendo l'SQL non valido (ricordate, SQL non supporta BOOL):

SELECT part_no, stock_pkg.is_in_stock(part_no) in_stock 
FROM parts_table 

che cosa ho bisogno è quello di trovare un modo di usare la funzione di cui sopra-call per generare un'uscita stringa valida (varchar) del formato:

PART_NO IN_STOCK 
------- ------------ 
AA  YES 
BB  NO 
CC  NO 

(Si può sostituire 'sì/no' per 'vero/falso ',' verde/rosso ',' tory/labor 'o anche numeric 1/0 per tutto quello che mi interessa - basta che l'output rientri in una delle due distinte categorie.)

Sfortunatamente, non ho il privilegio di riscrivere la funzione originale per restituire un diverso tipo di dati. E inoltre, ci sono migliaia di funzioni come questa sparse per l'applicazione più grande, rendendo poco pratico riscriverle tutte.

Quindi, in questo senso, la soluzione deve essere "generica" ​​(ovvero non specifica per questa chiamata di funzione). Ad esempio, non è sufficiente riscrivere la funzione come stock_pkg.is_in_stock_chr(), perché ciò significherebbe dover riscrivere tutte le altre funzioni simili anche nella mia applicazione.

ho già provato:

SELECT part_no, 
     CASE WHEN stock_pkg.is_in_stock(part_no) THEN 'y' ELSE 'n' END in_stock 
FROM parts_table 

e anche la mia funzione wrapper:

SELECT part_no, 
     my_bool_to_str(stock_pkg.is_in_stock(part_no)) in_stock 
FROM parts_table 

Ma anche avvolgendo booleani all'interno di altri costrutti funzionali non sembra essere consentita da Oracle SQL (almeno non in Oracle 10g).

C'è anche la possibilità di scrivere una sottocartella all'interno della colonna in_stock, ma che potrebbe essere eccessivamente complicata anche negli esempi estremi, e sarebbe anche specifica del caso.

Come ho detto, spero che ci sia una soluzione ingegnosa là fuori da qualche parte (o almeno una molto semplice, che mi capita di aver trascurato).

Grazie per il vostro tempo.

+0

Non mi è chiaro quale sia la tua domanda. Stai chiedendo come restituire un valore SQL in un tipo di dati booleano PL/SQL? –

+0

@DavidAldridge: Sto chiedendo come restituire un tipo di dati booleano PL/SQL (restituito da una funzione PL/SQL) in una query SQL run-of-the-mill. Ho una semplice piattaforma SQL-query che deve restituire il valore di questo valore booleano generato da PL/SQL, a un utente finale. – cartbeforehorse

risposta

6

È possibile scrivere il proprio involucro in questo modo:

CREATE OR REPLACE FUNCTION my_bool_to_str(f varchar2) RETURN VARCHAR2 IS 

    b varchar2(2); 

BEGIN 

    EXECUTE IMMEDIATE 'declare bl boolean; begin bl := ' || f || 
        '; if bl then :1 := ''y''; else :1 := ''n''; end if; end;' 
    using out b; 

    return b; 

END; 

Poi si può chiamare in questo modo:

SELECT part_no, 
     my_bool_to_str('stock_pkg.is_in_stock('|| part_no|| ')') in_stock 
FROM parts_table 

La differenza dal proprio involucro è che ottiene un varchar come input e non un booleano che il motore SQL non riconosce

+1

Questa soluzione è intelligente, ma necessita davvero di binding =) –

+0

Grazie per la correzione @VincentMalgrat! –

+0

Non pensavo che potessi associare i booleani, con 'execute immediate' o' dbms_sql'. Prendo ORA-00457 da questo, come ho fatto con la mia prima pugnalata simile. Mi sto perdendo qualcosa? –