2010-05-27 32 views
2

J'écris une application en utilisant Oracle 10g.Appel d'un appel de fonction dans une chaîne dans un Oracle Procédure

Je suis actuellement confronté à ce problème. Je prends "filename" comme paramètre de type varchar2.

Un exemple de valeur que ce nom de fichier peut contenir est: 'TEST || to_char (sysdate, 'DDD') '.

Dans la procédure, je souhaite obtenir la valeur de ce nom de fichier comme dans TEST147. Quand j'écris:

select filename 
into ffilename 
from dual; 

-je obtenir la valeur fFichier = test || to_char (sysdate, 'DDD') qui a du sens. Mais comment puis-je contourner ce problème et invoquer la fonction dans la valeur de chaîne?

Aide appréciée. Merci.

Répondre

1

Il est assez facile d'exécuter dynamiquement une chaîne ...

create or replace function fmt_fname (p_dyn_string in varchar2) 
    return varchar2 
is 
    return_value varchar2(128); 
begin 
    execute immediate 'select '||p_dyn_string||' from dual' 
     into return_value; 
    return return_value; 
end fmt_fname; 
/

Le problème se pose lorsque votre chaîne contient littéraux, les citations redoutés ...

SQL> select fmt_fname('TEST||to_char(sysdate, 'DDD')') from dual 
    2/
select fmt_fname('TEST||to_char(sysdate, 'DDD')') from dual 
              * 
ERROR at line 1: 
ORA-00907: missing right parenthesis 


SQL> 

Nous devons donc échapper les apostrophes, toutes, y compris celles que vous n'avez pas incluses dans votre chaîne affichée:

SQL> select * from t34 
    2/

     ID FILENAME 
---------- ------------------------------ 
     1 APC001 
     2 XYZ213 
     3 TEST147 


SQL> select * from t34 
    2 where filename = fmt_fname('''TEST''||to_char(sysdate, ''DDD'')') 
    3/

     ID FILENAME 
---------- ------------------------------ 
     3 TEST147 

SQL> 

EDIT

Juste pour des raisons d'équité, je sens que je dois souligner que la solution de Tony fonctionne tout aussi bien:

SQL> create or replace function fmt_fname (p_dyn_string in varchar2) 
    2  return varchar2 
    3 is 
    4  return_value varchar2(128); 
    5 begin 
    6  execute immediate 'begin :result := ' || p_dyn_string || '; end;' 
    7   using out return_value; 
    8  return return_value; 
    9 end; 
10/

Function created. 

SQL> select fmt_fname('''TEST''||to_char(sysdate, ''DDD'')') from dual 
    2/

FMT_FNAME('''TEST''||TO_CHAR(SYSDATE,''DDD'')') 
-------------------------------------------------------------------------------- 
TEST147 

SQL> 

En fait, en évitant le SELECT DUAL il est probablement mieux.

+0

L'exécution d'une entrée utilisateur non validée via SQL peut entraîner des attaques par injection SQL. L'utilisation de SELECT fournit au moins une certaine protection car elle limite ce que la fonction peut faire. Permettre l'injection PL/SQL peut conduire à toutes sortes de choses méchantes. –

2

La valeur de chaîne dans votre exemple est une expression non valide; il devrait être: 'TEST' || to_char (sysdate, 'DDD')

Évaluer que vous pourriez faire ceci:

execute immediate 'begin :result := ' || filename || '; end;' 
    using out v_string; 

v_string contiendra alors 'TEST147'.

+0

Merci pour votre aide. Il génère la valeur 'TEST147' mais renvoie une erreur sur dbms_output.put_line ('Résultat:' || v_string); Erreur: PLS-00201: l'identificateur 'TEST147' doit être déclaré. – DMS

+0

Je ne comprends pas. Que obtenez-vous si vous mettez dbms_output.put_line (filename) AVANT l'exécution immédiate? –

+0

l'erreur est levée lors de l'exécution de l'instruction d'exécution immédiate. l'autre méthode fournie par APC fonctionne. Merci pour votre temps. – DMS