【问题标题】:Oracle OCI: Query with Date fieldOracle OCI:使用日期字段查询
【发布时间】:2010-01-15 12:38:12
【问题描述】:

使用 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_DATAalways。一开始,日期值也是一个占位符,但我发现即使给出像 '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”语句,因为我不知道日期格式。这样我想为用户提供灵活性,而不是依赖特定的日期格式。这有意义吗?有什么建议吗?

【问题讨论】:

    标签: oracle date where oracle-call-interface clause


    【解决方案1】:

    您的 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',因为这种格式会被排序为原始日期。

    【讨论】:

    • 您好文森特,查询的第一个版本是使用 TO_DATE() 函数。问题就这样开始了。我的代码中的日期不会有字母,但我也不知道日期的具体格式。我在问题中添加了有关 OCI 应用程序如何工作的更多信息。
    【解决方案2】:

    记录是如何插入的?

    日期字段确实存储时间信息,因此当使用 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
    

    【讨论】:

    • 嗨,RC,我试过 trunc()。我添加了有关如何插入记录的更多信息。
    【解决方案3】:

    我想说你问错问题了。

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

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

    也就是说,如果这行得通

    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');
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-27
        • 2022-07-06
        • 1970-01-01
        • 2012-09-10
        • 1970-01-01
        • 2019-08-18
        • 2011-01-23
        • 1970-01-01
        相关资源
        最近更新 更多