在 Oracle 中编译用户定义函数时出现错误 PLS-00103

发布于 2024-09-12 07:13:03 字数 578 浏览 5 评论 0原文

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

I'm trying to create a user defined function in Oracle that will return a DATE when given a text argument containing a date substring. I've tried a couple ways of writing this, and all seem to throw the same error:

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;

the error:

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.

Any thoughts on this, and general UDF writing tips (and good references) are welcome! Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最舍不得你 2024-09-19 07:13:03

在存储过程中指定参数时,我们无法限制数据类型。也就是说,只需使用 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,但它们的大小实际上并未在存储过程签名中强制执行。但是,有一些解决方法,如 我在另一个线程中讨论了


顺便说一句,你为什么要使用正则表达式来解决这个问题?或者更确切地说,你想解决什么问题,而 Oracle 的格式非常宽容?面具。

We cannot restrict the datatype when specifying parameters in stored procedures. That is, just use VARCHAR2 rather than VARCHAR2(50).

Just to prove I'm reproducing your problem ...

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>

Now to fix it:

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."

Declaring a SQL TYPE to enforce sizing is a bit of overkill. We can declare SUBTYPEs in PL/SQL but their sizes are not actually enforced in stored procedure signatures. However there are workarounds as I discuss in this other thread.


As an aside, why are you using Regex to solve this problem? Or rather, what problem are you trying to solve which cannot be solved with TO_CHAR and TO_DATE? Oracle's pretty forgiving with format masks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文