在查询中使用参数时 Oracle ORA-01858

Posted

技术标签:

【中文标题】在查询中使用参数时 Oracle ORA-01858【英文标题】:Oracle ORA-01858 when using parameters in query 【发布时间】:2018-09-18 07:15:34 【问题描述】:

我有一个表,其中包含 TIMESTAMP(6) 类型的列,如果我尝试查询该表,只要我不对其进行参数化,一切都很好。

这行得通:

SELECT
  COUNT(*)
FROM
  t_data
WHERE
  DATA_TS >= TO_TIMESTAMP('13.09.18 11:30:00')
  AND   DATA_TS <= TO_TIMESTAMP('13.09.18 11:33:00');

但是,这会失败,因为 ORA-01858“在需要数字的地方发现了一个非数字字符”,提供了上述值。 我还尝试使用 NLS_PARAMETERS 中的格式掩码将参数包装在 TO_TIMESTAMP() 中。

SELECT
  COUNT(*)
FROM
  t_data
WHERE
  DATA_TS >= TO_TIMESTAMP(:AStart,'DD.MM.RR HH24:MI:SSXFF')
  AND   DATA_TS <= TO_TIMESTAMP(:AEnd,'DD.MM.RR HH24:MI:SSXFF');

有人知道是什么原因导致这个问题吗?

测试用例: 创建表

create table t_data ( 
    data varchar2(80), 
    data_ts timestamp 
);

插入数据

Insert into t_data (data,data_ts) VALUES ('TEST', systimestamp);

使用 &AStart 代替 :AStart 效果很好,如果这对某人有帮助的话

【问题讨论】:

:AStart:AEnd是什么数据类型? 我提供了:AStart with TO_TIMESTAMP('13.09.18 11:30:00') 从不在没有格式掩码的情况下使用 to_timestamp()。使用TO_TIMESTAMP('13.09.18 11:30:00', 'dd.mm.rr hh24:mi:ss') 谢谢,我会记住这一点,但这并不能解决问题 如果缺少格式掩码导致您出错的原因,我不会感到惊讶。 【参考方案1】:

您不能将TO_TIMESTAMP('13.09.18 11:30:00') 用作绑定变量内容。 DBMS 需要一个值,而不是代码。

因此,如果您的工具或编程语言允许,您可以传递时间戳或日期值,或者仅传递字符串 '13.09.18 11:30:00' 并在查询中包含 TO_DATE(:AStart, 'dd.mm.rr hh24:mi:ss')

更新:确保在将字符串作为绑定变量传递时不要包含引号。只传递字符串内容(例如13.09.18 11:30:00,而不是'13.09.18 11:30:00')。

【讨论】:

查看我的编辑,我试过了。同样的问题,只要我不将 '13.09.18 11:33:00' 替换为参数,它就可以工作。 所以你实际上传递了一个匹配格式'DD.MM.RR HH24:MI:SSXFF'的字符串,例如'13.09.18 11:30:00.00'? IE。您添加了格式字符串中提到的分数?这仍然失败,ORA-01858“在预期数字的地方发现了一个非数字字符”?而且您还尝试了TO_DATE 而不是TO_TIMESTAMP,正如我为您的原始日期字符串所推荐的那样,这也失败了? 没错,我已经尝试过这些组合。如果我使用这个 DATA_TS SYSTIMESTAMP 不是一个值;这是一个为您提供当前时间的功能。所以这又是你不能作为绑定变量传递的代码。你是如何传递价值的?您使用的是编程语言还是工具? 我正在为此使用 SQL Developer。我知道 SYSTIMESTAMP 是一个函数,但我确实希望在这种情况下工作。【参考方案2】:

你应该在函数内部使用参数

SELECT   COUNT(*)
FROM  t_data
WHERE   DATA_TS >= TO_TIMESTAMP(:AStart)
  AND   DATA_TS <= TO_TIMESTAMP(:AEnd);

【讨论】:

那么你的参数不是有效的时间戳检查真实输入值【参考方案3】:

真的是时间戳吗?因为,在我看来,您发布的值看起来像普通

无论如何:我相信您应该使用TO_TIMESTAMP 并为参数值提供适当的格式掩码。不是您应该应用 NLS 设置格式掩码,而是您在键入该参数的值时使用的那个。

例如:

SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';

Session altered.

SQL> select sysdate from dual;

SYSDATE
-------------------
18.09.2018 10:07:57

SQL> select to_timestamp('&par_ts', 'dd.mm.yy hh24:mi:ss') result from dual;
Enter value for par_ts: 18.09.18 10:08:23

RESULT
---------------------------------------------------------------------------
18.09.18 10:08:23,000000000

SQL>

如果您传递了不同格式的参数,格式掩码必须反映该更改:

SQL> select to_timestamp('&par_ts', 'mm-yyyy-dd hh24:mi:ss') result from dual;
Enter value for par_ts: 09-2018-18 10:10:15

RESULT
---------------------------------------------------------------------------
18.09.18 10:10:15,000000000

SQL>

这意味着您的查询应如下所示:

SELECT COUNT(*)
FROM  t_data
WHERE DATA_TS >= TO_TIMESTAMP(:AStart, 'dd.mm.yy hh24:mi:ss')
  AND DATA_TS <= TO_TIMESTAMP(:AEnd, 'dd.mm.yy hh24:mi:ss');

如有必要,请修复格式掩码。

【讨论】:

你是对的,我提供的值看起来像普通的日期。但是,即使从我的表中复制现有值并将其提供给参数也不起作用: VALUE: '13.09.18 11:32:43,000000000' ... DATA_TS >= TO_TIMESTAMP(:AStart,'DD.MM.RR HH24:MI:SSXFF') ... 考虑提供一个测试用例 - CREATE TABLE 和 INSERT INTO 示例数据,以及随后用于从该表中获取数据的 SELECT。很难猜测您究竟拥有什么、您做了什么以及 Oracle 是如何回应的。【参考方案4】:

感谢大家的贡献。我一直走错了路。

卸载旧版本的 SQL Developer 并安装当前版本后,问题消失了。我不知道是什么原因造成的,但它已经解决了。

这样做的结果是我现在对时间和日期格式有了更多的了解。

问候 属性

【讨论】:

以上是关于在查询中使用参数时 Oracle ORA-01858的主要内容,如果未能解决你的问题,请参考以下文章

Oracle存储过程在SSRS查询设计器中不起作用

执行 Oracle Ad Hoc 查询时绑定参数出错; ORA-00907: 缺少右括号

查询oracle数据库时,如何定义变量进行查询

Oracle12c多租户CDB 与 PDB 参数文件位置探讨查询 CDB 与 PDB 不同值的参数

Oracle模糊查询CONCAT参数个数无效

oracle游标怎么使用?创建完了 怎么用?