Oracle OCI:Запрос с полем даты
Вопрос
Клиент, скомпилированный с помощью OCI:10.2.0.4.0
Сервер:Oracle9i Enterprise Edition, выпуск 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'
не сработало.Я пробовал следующее:
- Я попробовал основы:запрос БД от клиента работает.Вот это доставляет мне неприятности
Работает следующее:
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() и «изменить набор сеансов 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');
На сервере:Возврат:«БанкоУан»
В приложении OCI:Возвращает «БанкоУан»
Итак, вопрос в том, почему приложение OCI дает разные результаты, если оба они обращаются к одному и тому же серверу БД?
Также, чтобы уточнить назначение приложения OCI:у него есть запрос, который должен быть настроен пользователем.Идея состоит в том, что пользователь адаптирует запрос по своему желанию в соответствии с полем даты, присутствующим в целевой БД, поэтому мне не следует включать в свой код операторы «alter session set nls_date_format», поскольку я не буду знать формат даты.Таким образом, я хочу предоставить пользователю гибкость и не полагаться на определенные форматы дат.Имеет ли это смысл?Какие-либо предложения?
Решение
ваш столбец 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'
потому что этот формат будет отсортирован как исходная дата.
Другие советы
Как вставлялись записи?
Поля даты хранят информацию о времени, и поэтому при вставке записей с помощью sysdate поле даты будет содержать разные «значения» для записей в течение этого дня.Когда вы выполняете date_proc = '05-JUL-08', вы говорите, что date_proc точно равно 5 июля 2008 года в 12:01:00.Если вы вставили запись в 12:01 с помощью sysdate, она не будет возвращена.Вы пробовали использовать промежуточный или 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
Я бы сказал, что вы задаете неправильный вопрос.
Oracle полагается на совместное использование SQL для повышения производительности, и когда вы вставляете строку, например «20080705», SQL не может быть разделен.Подробности здесь.
Таким образом, значение данных должно быть заполнителем и иметь правильный тип данных (ДАТА).Пример здесь должен помочь это сделать.
Тем не менее, если это сработает
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');
У нас только что возникла эта ошибка (OCI_NO_DATA), вызванная тем, что кто-то изменил час дня на своем компьютере.Когда они вернули дату/время в нужное положение, приложение начало работать нормально.