使用日期值执行 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_FORMAT
将 varchar2
参数隐式转换为 timestamp
。对于不同的会话,这可能会有所不同,因此至少有一些会话可能会出错,因为字符串与该会话的NLS_TIMESTAMP_FORMAT
的格式不匹配。通过显式调用 to_timestamp
或传递时间戳文字,传递实际时间戳会更好。
然后您的过程接受timestamp
参数并将它们传递给to_date
函数。 to_date
函数不接受 timestamp
类型的参数,它只接受 varchar2
类型的参数。这迫使 Oracle 再次使用会话的 NLS_TIMESTAMP_FORMAT
将 timestamp
参数隐式转换为 varchar2
。如果会话的NLS_TIMESTAMP_FORMAT
与to_date
调用中的显式格式掩码不匹配,您将收到错误消息,或者转换将返回您不期望的结果。
如果表中的列实际上是date
类型,则可以直接将date
与timestamp
进行比较。所以似乎没有任何理由在这里打电话给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 参数过程时,月份不是有效月份的主要内容,如果未能解决你的问题,请参考以下文章