2010-08-03 6 views
3

J'essaye de créer une fonction définie par l'utilisateur dans Oracle qui renverra une DATE quand donné un argument de texte contenant une chaîne de date. Je l'ai essayé deux manières d'écrire cela, et tous semblent jeter la même erreur:Erreur PLS-00103 compilant la fonction définie par l'utilisateur dans Oracle

CREATE OR REPLACE FUNCTION lm_date_convert (lm_date_in IN VARCHAR2(50)) 
    RETURN DATE DETERMINISTIC IS 
BEGIN 
    RETURN(TO_DATE(REGEXP_REPLACE(lm_date_in, '([[:digit:]]{2})[-/.]*([[:digit:]]{2})[-/.]*([[:digit:]]{4})','\3-\1-\2'), 'YYYY-MM-DD')); 
END; 

l'erreur:

FUNCTION lm_date_convert Compiled. 1/46
PLS-00103: Encountered the symbol "(" when expecting one of the following:

:= .) , @ % default character The symbol ":=" was substituted for "(" to continue.

Toute réflexion sur ce sujet et des conseils d'écriture UDF générale (et bon références) sont les bienvenus! Merci.

Répondre

12

Nous ne pouvons pas restreindre le type de données lors de la spécification des paramètres dans les procédures stockées. Autrement dit, utilisez simplement VARCHAR2 plutôt que VARCHAR2 (50).

Juste pour prouver que je suis reproduire votre problème ...

SQL> CREATE OR REPLACE FUNCTION lm_date_convert (lm_date_in IN VARCHAR2(50)) 
    2 RETURN DATE DETERMINISTIC IS 
    3 BEGIN 
    4 RETURN(TO_DATE(REGEXP_REPLACE(lm_date_in, '([[:digit:]]{2})[-/.]*([[:digit:]]{2})[-/.]*([[:digit:]]{4})','\3-\1-\2'), 'YYYY-MM-DD')); 
    5 END; 
    6/

Warning: Function created with compilation errors. 

SQL> sho err 
Errors for FUNCTION LM_DATE_CONVERT: 

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
1/49  PLS-00103: Encountered the symbol "(" when expecting one of the 
     following: 
     := .) , @ % default character 
     The symbol ":=" was substituted for "(" to continue. 

SQL> 

Maintenant, pour y remédier:

SQL> ed 
Wrote file afiedt.buf 

    1 CREATE OR REPLACE FUNCTION lm_date_convert (lm_date_in IN VARCHAR2) 
    2 RETURN DATE DETERMINISTIC IS 
    3 BEGIN 
    4 RETURN(TO_DATE(REGEXP_REPLACE(lm_date_in, '([[:digit:]]{2})[-/.]*([[:digit:]]{2})[-/.]*([[:digit:]]{4})','\3-\1-\2'), 'YYYY-MM-DD')); 
    5* END; 
SQL> r 
    1 CREATE OR REPLACE FUNCTION lm_date_convert (lm_date_in IN VARCHAR2) 
    2 RETURN DATE DETERMINISTIC IS 
    3 BEGIN 
    4 RETURN(TO_DATE(REGEXP_REPLACE(lm_date_in, '([[:digit:]]{2})[-/.]*([[:digit:]]{2})[-/.]*([[:digit:]]{4})','\3-\1-\2'), 'YYYY-MM-DD')); 
    5* END; 

Function created. 

SQL> 

"If you really do want a VARCHAR2(50) then declare a type of VARCHAR2(50) and use the type."

Déclarer un type SQL pour appliquer le calibrage est une peu d'overkill. Nous pouvons déclarer SUBTYPEs en PL/SQL mais leurs tailles ne sont pas réellement appliquées dans les signatures de procédures stockées. Cependant, il existe des solutions de contournement telles que I discuss in this other thread. En outre, pourquoi utilisez-vous Regex pour résoudre ce problème? Ou plutôt, quel problème essayez-vous de résoudre qui ne peut pas être résolu avec TO_CHAR et TO_DATE? Oracle est joli pardonner avec des masques de format.

+0

merci pour la solution - j'espérais que ce serait quelque chose comme ça. J'ai des chaînes sous différentes formes, comme '2010-08-03 00: 00: 00.0' que j'ai besoin de traiter dans les objets de date. Je suppose que je pourrais utiliser 'TO_DATE (SUBSTR ('2010-08-03 00: 00: 00.0', 1, 10), 'AAAA-MM-JJ')' devrais-je faire cela au lieu d'utiliser Regex? des pointeurs sur quand utiliser ou éviter Regex, et pourquoi? merci pour l'aide! – Stew

+0

Si vous voulez vraiment un VARCHAR2 (50) alors déclarez un type de VARCHAR2 (50) et utilisez le type. – darreljnz