Oracle OCI:带日期字段的查询

发布于 2024-08-17 23:19:30 字数 1817 浏览 14 评论 0原文

使用 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 始终。一开始,日期值也是一个占位符,但我发现即使给出像 '05-JUL-08' 这样的文字也不起作用。我尝试了以下操作:

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

    从日志中选择 CODIGO,其中 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”语句,因为我不知道日期格式。这样我想为用户提供灵活性,并且不依赖于特定的日期格式。这有道理吗?有什么建议吗?

Client compiled with OCI: 10.2.0.4.0
Server: Oracle9i Enterprise Edition Release 9.2.0.4.0

The problematic query is:

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

Table description:

SQL>describe LOG;

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

As simple as it might look, when executed directly on the server with SQLPlus, it returns a result, but when executed from the app that uses OCI, this query returns OCI_NO_DATA always. In the beginning, the date value was also a placeholder, but I found out that even giving a literal like '05-JUL-08' didn't work. I have tried the following:

  • I've tried the basics: querying the DB from the client does work. It's this one that gives me trouble
  • The following does work:

    SELECT CODIGO FROM LOG WHERE TEL = :telnumber
    
  • Executing ALTER SESSION SET NLS_DATE_FORMAT="DD-MM-YYYY"; before the query in both the server and the client. Same result: server returns data, client OCI_NO_DATA

  • Tried changing DATE_PROC format, combining this with the use of TO_DATE(). Same result.
  • Searched, searched, searched. No answer

I'm a bit desperate to find an answer, would appreciate any help and can provide as many further details as needed. Thanks.

--- Further info ---

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

I have tried different combinations using trunc() and "alter session set nls_date_format"... and this is what I get:

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

In server: Returns: "BancoOne" (good value)
In OCI app: Returns OCI_NO_DATA

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

In server: Returns: "BancoOne"
In OCI app: Returns "BancoOne"

So the point is, why is the OCI app giving different results if both are accessing the same DB server?

Also, to clarify the purpose of the OCI app: it has a query to be configured by the user. The idea is that the user will adapt the query as desired to fit with the Date field present in the destination DB, that's why I should not include "alter session set nls_date_format" statements in my code, as I will not know the date format. This way I want to provide flexibility to the user, and don't rely on specific date formats. Does this make sense? Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清风无影 2024-08-24 23:19:30

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

试试这个:

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' 因为这种格式将按原始日期排序。

your column DATE_PROC is a DATE, you should always compare it to a date and never rely on the implicit data conversion.

Try this:

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

or this:

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

If you can, refrain from using a date format in your code that uses letters for months (because the code will fail when you change the default language) and only two chars for years (ambiguity of century). I like to use 'YYYY/MM/RR' because this format will be sorted as the original date.

孤寂小茶 2024-08-24 23:19:30

记录是如何插入的?

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

How were the records inserted?

Date fields do store time information, and thus when inserting records using sysdate, the date field will contain different "values" for records within that day. When you execute date_proc = '05-JUL-08', you are saying where date_proc equals exactly the 5th of July 2008 at 12:01:00. If you inserted the record at 12:01 with sysdate, it will not be returned. Have you tried using a between or trunc?

Here is an example:

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
旧人哭 2024-08-24 23:19:30

我想说你问错了问题。

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

I'd say you are asking the wrong question.

Oracle relies on sharing SQL for performance and when you stick a string in, like '20080705', the SQL can't be shared. Details here.

So the data value should be a placeholder and should be of the correct data-type (DATE). The example here should help to do that.

That said, if this works

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

but this doesn't

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

I'd be trying

SELECT TO_CHAR(DATE_PROC,'DD-MM-YYYY HH24:MI:SS') FROM LOG 
WHERE TEL = 11223344 AND 
trunc(DATE_PROC) = TO_DATE('20080705', 'YYYYMMDD');
与之呼应 2024-08-24 23:19:30

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

We just had this error (OCI_NO_DATA) get caused by someone changing the hour of the day on their pc. When they put the date/time back to the right time, the application started working ok.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文