使用日期值执行 IN 参数过程时,月份不是有效月份

Posted

技术标签:

【中文标题】使用日期值执行 IN 参数过程时,月份不是有效月份【英文标题】:Not a valid month when executing an IN parameter procedure with date value 【发布时间】:2014-05-07 17:32:38 【问题描述】:
CREATE OR REPLACE PROCEDURE PROC1(
   V_STARTTIME    IN TIMESTAMP ,
   V_ENDTIME      IN TIMESTAMP )
BEGIN
INSERT INTO TAB1
SELECT COINS FROM TAB2
WHERE DATE BETWEEN TO_DATE(V_STARTTIME,'mm/dd/yyyy hh:mi:ss aM') AND TO_DATE(V_ENDTIME    ,'mm/dd/yyyy hh:mi:ss aM');
END;

SAMPLE DATE in Tab2 5/5/2014 9:46:38.000000 AM

我的脚本在一系列日期之间运行。这两个日期是 IN 参数。

当我执行程序时

执行 proc1('5/05/2014 11:25:00 AM','5/05/2014 12:25:00 PM')

我收到无效月份错误。 知道如何解决这个问题吗? 谢谢

【问题讨论】:

【参考方案1】:

您的过程采用timestamp 类型的参数。您实际上是在调用中传递 varchar2 类型的参数。这会强制 Oracle 使用会话的 NLS_TIMESTAMP_FORMATvarchar2 参数隐式转换为 timestamp。对于不同的会话,这可能会有所不同,因此至少有一些会话可能会出错,因为字符串与该会话的NLS_TIMESTAMP_FORMAT 的格式不匹配。通过显式调用 to_timestamp 或传递时间戳文字,传递实际时间戳会更好。

然后您的过程接受timestamp 参数并将它们传递给to_date 函数。 to_date 函数不接受 timestamp 类型的参数,它只接受 varchar2 类型的参数。这迫使 Oracle 再次使用会话的 NLS_TIMESTAMP_FORMATtimestamp 参数隐式转换为 varchar2。如果会话的NLS_TIMESTAMP_FORMATto_date 调用中的显式格式掩码不匹配,您将收到错误消息,或者转换将返回您不期望的结果。

如果表中的列实际上是date 类型,则可以直接将datetimestamp 进行比较。所以似乎没有任何理由在这里打电话给to_date。但是,根据您的示例数据,您的表中的列似乎实际上是 timestamp 类型,而不是您的代码所暗示的 date,因为 date 没有小数秒精度。如果是这种情况,在SELECT 语句中调用to_date 就更没有意义了,因为您的参数实际上是timestamp 类型,而您的列是timestamp 类型。只需比较 timestamp 的值。

因此,我的猜测是你想要类似的东西

CREATE OR REPLACE PROCEDURE PROC1(
   V_STARTTIME    IN TIMESTAMP ,
   V_ENDTIME      IN TIMESTAMP )
BEGIN
  INSERT INTO TAB1( <<column name>> )
    SELECT COINS 
      FROM TAB2
     WHERE <<timestamp column name>> BETWEEN v_starttime AND v_endtime;
END;

并且您想通过传递实际时间戳来调用该过程。使用时间戳文字

Execute proc1(timestamp '2014-05-05 11:25:00', timestamp '2014-05-05 12:25:00' )

或通过显式调用to_timestamp

execute proc1( to_timestamp( '5/05/2014 11:25:00 AM', 'MM/DD/YYYY HH:MI:SS AM' ),
               to_timestamp( '5/05/2014 12:25:00 PM', 'MM/DD/YYYY HH:MI:SS AM' ) );

这应该消除当前正在发生的所有隐式类型转换。

【讨论】:

感谢贾斯汀的详尽解释。它就像一个魅力!

以上是关于使用日期值执行 IN 参数过程时,月份不是有效月份的主要内容,如果未能解决你的问题,请参考以下文章

ORA-01843 不是有效月份 - 比较日期

Firefox 输入类型 = 日期最小值未在最小有效月份打开

从存储过程刷新物化视图时出错(不是有效月份)

检查日期是不是对选定的月份有效 Django 表单

“ORA-01843: 不是一个有效的月份”错误

根据月份和年份获取日期