在查询中使用参数时 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 Ad Hoc 查询时绑定参数出错; ORA-00907: 缺少右括号