2

使用OCI编译的客户端:10.2.0.4.0
服务器:Oracle9i Enterprise Edition Release 9.2.0.4.0

有问题的查询是:

SELECT CODIGO FROM LOG WHERE TEL = :telnumber AND DATE_PROC = '05-JUL-08'

表说明:

SQL>describe LOG;

TEL NOT NULL VARCHAR2(15)
CODIGO NOT NULL VARCHAR2(20)
DATE_PROC NOT NULL DATE

看起来很简单,当使用 SQLPlus 直接在服务器上执行时,它会返回一个结果,但是当从使用 OCI 的应用程序中执行时,此查询会返回OCI_NO_DATA always。一开始,日期值也是一个占位符,但我发现即使给出一个字面值'05-JUL-08'也不起作用。我尝试了以下方法:

  • 我已经尝试了基础知识:从客户端查询数据库确实有效。就是这个给我带来麻烦
  • 以下确实有效:

    SELECT CODIGO FROM LOG WHERE TEL = :telnumber
    
  • ALTER SESSION SET NLS_DATE_FORMAT="DD-MM-YYYY";在服务器和客户端的查询之前执行。结果相同:服务器返回数据,客户端OCI_NO_DATA

  • 尝试更改DATE_PROC格式,将其与TO_DATE(). 结果相同。
  • 搜索,搜索,搜索。没有答案

我有点急于找到答案,希望得到任何帮助,并可以根据需要提供更多详细信息。谢谢。

---更多信息---

update log set DATE_PROC = TO_DATE('20080705162918', 'YYYYMMDDHH24MISS') where CODIGO='BancoOne';

我使用 trunc() 和“alter session set nls_date_format”尝试了不同的组合......这就是我得到的:

SELECT CODIGO FROM LOG WHERE TEL = 11223344 AND DATE_PROC = TO_DATE('20080705162918', 'YYYYMMDDHH24MISS');

在服务器中:返回:“BancoOne”(良好的价值)
在 OCI 应用程序中:返回 OCI_NO_DATA

SELECT CODIGO FROM LOG WHERE TEL = 11223344 AND trunc(DATE_PROC) = TO_DATE('20080705', 'YYYYMMDD');

在服务器中:返回:“BancoOne”
在 OCI 应用程序中:返回“BancoOne”

所以关键是,如果 OCI 应用程序都访问同一个数据库服务器,为什么会给出不同的结果?

此外,为了澄清 OCI 应用程序的目的:它有一个由用户配置的查询。这个想法是用户将根据需要调整查询以适应目标数据库中存在的日期字段,这就是为什么我不应该在我的代码中包含“alter session set nls_date_format”语句,因为我不知道日期格式。这样我想为用户提供灵活性,而不是依赖特定的日期格式。这有意义吗?有什么建议么?

4

4 回答 4

2

您的 DATE_PROC 列是 DATE,您应该始终将其与日期进行比较,并且永远不要依赖隐式数据转换。

试试这个:

SELECT CODIGO FROM LOG WHERE TEL = :telnumber AND DATE_PROC = DATE '2008-07-05'

或这个:

SELECT CODIGO 
  FROM LOG 
 WHERE TEL = :telnumber 
   AND DATE_PROC = to_date('05-JUL-08', 'DD-MON-RR')

如果可以,请避免在代码中使用使用字母表示月份的日期格式(因为更改默认语言时代码将失败)并且年份仅使用两个字符(世纪的歧义)。我喜欢使用'YYYY/MM/RR',因为这种格式将被排序为原始日期。

于 2010-01-15T13:27:04.620 回答
0

记录是如何插入的?

日期字段确实存储时间信息,因此当使用 sysdate 插入记录时,日期字段将包含当天记录的不同“值”。当您执行 date_proc = '05-JUL-08' 时,您说的是 date_proc 正好等于 2008 年 7 月 5 日 12:01:00。如果您在 12:01 使用 sysdate 插入记录,则不会返回。您是否尝试过使用 between 或 trunc?

这是一个例子:

drop table test_date;
create table test_date (id number, ud date);

insert into test_date values (1, '15-jan-10');
insert into test_date values (2, '15-jan-10');
insert into test_date values (3, '15-jan-10');
insert into test_date values (6, sysdate);    -- sysdate as of writing is 15-JAN-2010 08:01:55
insert into test_date values (7, sysdate);    -- sysdate as of writing is 15-JAN-2010 08:01:55
insert into test_date values (8, '16-jan-10');
commit;

select id, ud, to_char(ud, 'dd-MON-yyyy HH:MM:SS') from test_date where ud = '15-jan-10';
---------------------- ------------------------- --------------------
1                      15-JAN-10                 15-JAN-2010 12:01:00                                                        
2                      15-JAN-10                 15-JAN-2010 12:01:00                                                        
3                      15-JAN-10                 15-JAN-2010 12:01:00      

select id, ud, to_char(ud, 'dd-MON-yyyy HH:MM:SS') from test_date where trunc(ud) = '15-jan-2010';
---------------------- ------------------------- --------------------
1                      15-JAN-10                 15-JAN-2010 12:01:00                                                        
2                      15-JAN-10                 15-JAN-2010 12:01:00                                                        
3                      15-JAN-10                 15-JAN-2010 12:01:00                                                        
6                      15-JAN-10                 15-JAN-2010 08:01:55                                                        
7                      15-JAN-10                 15-JAN-2010 08:01:55
于 2010-01-15T12:56:11.187 回答
0

我会说你问错了问题。

Oracle 依靠共享 SQL 来提高性能,当您插入一个字符串(例如“20080705”)时,就无法共享 SQL。详情在这里

所以数据值应该是一个占位符并且应该是正确的数据类型(DATE)。这里的例子应该有助于做到这一点。

也就是说,如果这有效

SELECT CODIGO FROM LOG 
WHERE TEL = 11223344 AND 
trunc(DATE_PROC) = TO_DATE('20080705', 'YYYYMMDD');

但这不是

SELECT CODIGO FROM LOG 
WHERE TEL = 11223344 
AND DATE_PROC = TO_DATE('20080705162918', 'YYYYMMDDHH24MISS');

我会尝试

SELECT TO_CHAR(DATE_PROC,'DD-MM-YYYY HH24:MI:SS') FROM LOG 
WHERE TEL = 11223344 AND 
trunc(DATE_PROC) = TO_DATE('20080705', 'YYYYMMDD');
于 2010-01-17T21:59:49.683 回答
0

我们刚刚遇到这个错误(OCI_NO_DATA)是由某人在他们的电脑上更改一天中的时间引起的。当他们将日期/时间恢复到正确的时间时,应用程序开始正常工作。

于 2013-04-26T13:52:03.320 回答