2015-10-15 3 views
5

В моей таблице myTab есть столбец startDate, который имеет тип данных «DATE». Данные в этом столбце хранятся как dd.mm.yyyy.Oracle использует LIKE '%' в DATE

Теперь я пытаюсь получить данные с этим запросом:

SELECT * FROM myTab WHERE startDate like '%01.2015" 

Как-то не работает, и я не знаю, почему.

Надеюсь, кто-то может помочь.

+0

Если вы хотите, чтобы все строки в январе 2015 Использование 'где to_char (STARTDATE«пн-YYYY») = 'январе- 2015 '; ' – Mihai

+0

Взгляните на [Oracle SQL сравнение DATEs возвращает неверный результат] (http://stackoverflow.com/questions/29005398/oracle-sql-comparison-of-dates-returns-wrong-result/29005418# 29005418) –

ответ

18

Чтобы сделать текстовый поиск в дату, вам нужно будет преобразовать дату в текст.

Это более эффективно, если вы подсчитаете первую и последнюю дату того, что вы хотите найти, и получите все между ними. Таким образом, это делается как числовые сравнения вместо матча текст шаблона, и он может использовать индекс, если есть один:

SELECT * FROM myTab WHERE startDate >= DATE '2015-01-01' AND startDate < DATE '2015-02-01' 
+0

Я был бы признателен, если вы также отметите, что ** ПОЧЕМУ ** используя ** диапазон дат ** состояние здесь лучше. В основном речь идет о производительности, т. Е. Использовании индекса дерева B * (если есть). –

+0

@LalitKumarB: Хорошая точка. – Guffa

+0

"* Таким образом, это простое числовое сравнение вместо соответствия шаблону текста *« Нет, это не так, это вовсе не цифровое сравнение. В Oracle ** DATE ** и ** NUMBER ** совершенно разные. ' –

2

Если тип поля «DATE», то значение не сохраняется как строка, это число управляется Oracle, так что вы должны преобразовать его в строку:

SELECT * FROM myTab WHERE to_char(startDate, 'MM.YYYY') = '01.2015'; 

вы также можете использовать диапазоны дат в запросах SQL:

SELECT * FROM myTab 
WHERE startDate 
BETWEEN to_date('01.01.2015', 'DD.MM.YYYY') 
AND  to_date('31.01.2015', 'DD.MM.YYYY'); 
+1

Прочитайте сначала о неявных преобразованиях данных: здесь http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements002.htm # i53062 Oracle автоматически преобразует дату в varchar в этом случае, ваш ответ неточен. – krokodilko

+0

to_char() явно: http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements002. htm # SQLRF51054 – mbk

2
SELECT * FROM myTab WHERE TO_CHAR(startDate,'dd.mm.yyyy') LIKE '%01.2015' 
+0

Твой путь вроде работал. Теперь у меня проблема: другие Даты не работают. Если я попытаюсь использовать «% 01.2013», я не получаю никаких данных, но я знаю, что есть Даты в этом диапазоне ... – Ovoxo

+0

@Lalit, могу ли я смиренно предложить вам немного расслабить свой тон? Этот ответ не «полностью ошибочен», это не самое лучшее. Фактически, этот ответ * будет работать *, хотя есть гораздо более эффективные способы решения проблемы и, действительно, * не *, полагаются на неявное преобразование типа данных. –

+0

@Jeffrey, достаточно справедливо :-) –

1

Относительно вашего фактического вопроса «Почему-то это не работает, и я не знаю почему».

Oracle делает неявное преобразование от DATE до VARHCAR2, однако он использует значение по умолчанию NLS_DATE_FORMAT, которое, вероятно, отличается от того, что вы используете в своем запросе.

1

Данные в этой колонке хранятся как dd.mm.yyyy.

Оракул не хранит дату в формате, который вы видите. Он хранит его внутренне в проприетарном формате в 7 байт с каждым байтом, хранящим разные компоненты значения datetime.

ГДЕ STARTDATE как «% 01,2015"

Вы сравниваете DATE с STRING, что бессмысленно.

С точки зрения производительности, вы должны используйте диапазон дат, так что если есть какие-либо регулярные INDEX на дату col umn, он будет использоваться.

SELECT * FROM table_name WHERE date_column BETWEEN DATE '2015-01-01' AND DATE '2015-02-01' 

Чтобы понять, почему диапазон дат условие лучше с точки зрения производительности , взгляните на мой ответ here.

0

Я решил свою проблему таким образом. Благодарим вас за предложения по улучшению. Пример в C#.

string dd, mm, aa, trc, data; 
dd = nData.Text.Substring(0, 2); 
mm = nData.Text.Substring(3, 2); 
aa = nData.Text.Substring(6, 4); 
trc = "-"; 
data = aa + trc + mm + trc + dd; 

"Select * From bdPedidos Where Data Like '%" + data + "%'"; 
0

Чтобы обеспечить более детальный ответ и решить проблему этого https://stackoverflow.com/a/42429550/1267661 ответить в.

В Oracle столбец типа «дата» не является числом или строкой, это значение «datetime» с указанием года, месяца, дня, часа, минуты и секунды. время по умолчанию всегда полночь «00:00:00»

Запрос:

Select * From bdPedidos Where Data Like '%" + data + "%'" 

не будет работать при любых обстоятельствах, так как столбец дата не является строкой, используя «как» силы Oracle сделать преобразование из значения даты в значение строки. Строковое значение может быть год-месяц-день-время или месяц-день-год-год или день-месяц-год-время, все зависит от того, как конкретный экземпляр Oracle установил параметр NLS_DATE_FORMAT для отображения дат в виде строк.

Правильный путь, чтобы охватить все возможные раз в день:

Select * 
From bdPedidos 
Where Data between to_date('" + data + " 00:00:00','yyyy-mm-dd hh24:mi:ss') 
       and to_date('" + data + " 23:59:59','yyyy-mm-dd hh24:mi:ss') 
+0

Запрос - это строка, встроенная внутри C#, поэтому необходимы стартовая и последняя цитаты – alvalongo