5

我正在尝试在 Oracle 中创建一个用户定义的函数,当给定包含日期子字符串的文本参数时,它将返回一个 DATE。我已经尝试了几种写这个的方法,而且似乎都抛出了同样的错误:

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;

错误:

功能 lm_date_convert 已编译。1/46
PLS-00103:在预期以下情况之一时遇到符号“(”:

:= 。) , @ % 默认字符符号 ":=" 被替换为 "(" 以继续。

欢迎对此提出任何想法,以及一般的 UDF 写作技巧(和良好的参考资料)!谢谢。

4

1 回答 1

21

在存储过程中指定参数时,我们不能限制数据类型。也就是说,只需使用 VARCHAR2 而不是 VARCHAR2(50)。

只是为了证明我正在重现您的问题...

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>

现在修复它:

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> 

“如果你真的想要一个 VARCHAR2(50),那么声明一个 VARCHAR2(50) 类型并使用该类型。”

声明一个 SQL TYPE 来强制调整大小有点矫枉过正。我们可以在 PL/SQL 中声明 SUBTYPE,但它们的大小实际上并未在存储过程签名中强制执行。但是,正如我在另一个线程中讨论的那样,有一些解决方法。


顺便说一句,您为什么要使用正则表达式来解决这个问题?或者更确切地说,您要解决哪些问题无法用 TO_CHAR 和 TO_DATE 解决?Oracle 对格式掩码非常宽容。

于 2010-08-03T16:46:59.153 回答