Oracle PL/SQL 不能识别 DATE 输入?

Posted

技术标签:

【中文标题】Oracle PL/SQL 不能识别 DATE 输入?【英文标题】:Oracle PL/SQL does not recognize a DATE input? 【发布时间】:2018-04-08 12:58:22 【问题描述】:

我有包裹:

create or replace PACKAGE overload_pkg IS
  PROCEDURE what_am_i (p_x IN VARCHAR2);
  PROCEDURE what_am_i (p_x IN NUMBER);
  PROCEDURE what_am_i (p_x IN DATE);
END overload_pkg;

和身体:

create or replace PACKAGE BODY overload_pkg IS
  PROCEDURE what_am_i (p_x IN VARCHAR2) IS
  BEGIN 
    pri('Here I am, a VARCHAR2');
  END what_am_i;
  PROCEDURE what_am_i (p_x IN NUMBER) IS
  BEGIN 
    pri('Here I am, a NUMBER');
  END what_am_i;
  PROCEDURE what_am_i (p_x IN DATE) IS
    BEGIN 
    pri('Here I am, a DATE');
  END what_am_i;
END overload_pkg;

然而,当我调用包 PROCEDUREs 时:

BEGIN 
  overload_pkg.what_am_i('varchar2');
  overload_pkg.what_am_i(1234);
  overload_pkg.what_am_i('2018-04-06');
END;

或我能想到的任何其他日期格式,Oracle 认为它是 VARCHAR 或 NUMBER。输出:

我在这里,一个 VARCHAR2 我在这里,一个号码 我在这里,一个 VARCHAR2

声明已处理。

唯一有效的是……

BEGIN 
  overload_pkg.what_am_i('varchar2');
  overload_pkg.what_am_i(1234);
  overload_pkg.what_am_i(to_DATE('08-APR-2018', 'DD-MON-YYYY'));
END;

但我认为 Oracle 可以识别日期,因为它会进行隐式转换。我很困惑。

提前致谢。

【问题讨论】:

overload_pkg.what_am_i('2018-04-06'); Oracle 在这里工作正常。您正在传递一个字符串 - 一系列由单引号包围的字符。字符串中的值可以成功转换为日期的事实并没有改变这一点。如果您将第二次呼叫更改为 overload_pkg.what_am_i('1234');,您希望会发生什么? Oracle 会将字符串转换为日期仅在需要时 - 也就是说,如果日期是必需的。在您的情况下,字符串可以正常工作 - Oracle 不需要将其转换为字符串来“让事情正常工作”。也许如果您没有定义一个接受字符串的版本,它会尝试转换为日期 - 但即便如此,这也会失败,因为 Oracle 确实 not “识别日期”(不管你怎么想) ;它仅“识别日期”与会话 NLS_DATE_FORMAT 参数匹配。如果您的NLS_DATE_FORMAT'dd-MON-yyyy',则输入'2018-04-06' 将不会被识别为日期。 @mathguy,更多好信息,谢谢! 【参考方案1】:

这是意料之中的;当你跑的时候

overload_pkg.what_am_i('2018-04-06');

你向程序传递了一个字符串;看到单引号和中间的 something 了吗?嗯,是的 - 这是一个字符串,VARCHAR2

这里不计算隐式转换;如果您在某些查询中使用该字符串(看起来像DATE),它可能会。 Oracle 不必在这里转换任何东西。您发送了一个字符串,它被检测到,并执行了适当的过程。

如果你想传递DATE,那么就这样做 - 使用DATE literal,它总是以DATE 'YYYY-MM-DD' 格式出现,或者应用TO_DATE 函数适当的格式掩码。

【讨论】:

谢谢,@Littlefoot。这很有帮助【参考方案2】:

你可以使用DATE literal:

BEGIN
   overload_pkg.what_am_i(DATE '2018-04-06');
END

来自How Subprogram Calls Are Resolved:

要解决同一范围级别的可能同名子程序之间的调用,编译器必须找到实际参数和形式参数之间的精确匹配。 它们必须在数量、顺序和数据类型上匹配(除非为某些形式参数分配了默认值)。如果未找到匹配项或找到多个匹配项,则编译器会生成语义错误。

【讨论】:

太棒了!谢谢!我在这里学习。我用过所有我能想到的日期格式,但不知道“DATE 文字”实际上包含“DATE”这个词。

以上是关于Oracle PL/SQL 不能识别 DATE 输入?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Plus 无法识别 Oracle PL/SQL 语句

Oracle Pl sql 登录时提示 “监听程序当前无法识别连接描述符中请求的服务” 。

Oracle SQL 或 PL/SQL:如何仅在上升趋势或下降趋势结束时识别烛台形态并在列中设置标志?

oracle sql pl/sql 如何减去日期/工作周

Oracle SQL - 如何在没有 PL/SQL 的情况下检查合同的延续

Oracle PL / SQL触发器,在UPDATE之前/之后仅用于识别表中已修改的列