【问题标题】:Error PLS-00103 compiling user-defined function in Oracle在 Oracle 中编译用户定义函数时出现错误 PLS-00103
【发布时间】:2011-03-24 20:08:39
【问题描述】:

我正在尝试在 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 写作技巧(和良好的参考资料)!谢谢。

【问题讨论】:

    标签: oracle function plsql user-defined-functions pls-00103


    【解决方案1】:

    在存储过程中指定参数时,我们不能限制数据类型。也就是说,只需使用 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,但它们的大小实际上并未在存储过程签名中强制执行。但是有I discuss in this other thread 的解决方法。


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

    【讨论】:

    • 感谢您的解决方案——我希望它会是这样的。我有不同形式的字符串,例如 '2010-08-03 00:00:00.0' 我需要处理成日期对象。我想我可以使用TO_DATE(SUBSTR('2010-08-03 00:00:00.0', 1, 10), 'YYYY-MM-DD') 我应该这样做而不是使用正则表达式吗?关于何时使用或避免正则表达式的任何指示,为什么?感谢您的帮助!
    • 如果你真的想要一个 VARCHAR2(50) 然后声明一个 VARCHAR2(50) 类型并使用该类型。
    猜你喜欢
    • 2011-01-21
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 2021-08-11
    • 1970-01-01
    相关资源
    最近更新 更多