Oracle использует LIKE '%' на DATE

В моей таблице myTab есть столбец startDate с типом данных "DATE". Данные в этом столбце хранятся как dd.mm.yyyy.

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

SELECT * FROM myTab WHERE startDate like '%01.2015"

Почему-то не работает, не знаю почему.

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


person Mihawk    schedule 15.10.2015    source источник
comment
Если вам нужны все строки за январь 2015 года, используйте where to_char(startDate ,'Mon-YYYY')='Jan-2015';.   -  person Mihai    schedule 15.10.2015
comment
Взгляните на Сравнение DATE Oracle SQL возвращает неправильный результат   -  person Lalit Kumar B    schedule 15.10.2015


Ответы (8)


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

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

SELECT * FROM myTab WHERE startDate >= DATE '2015-01-01' AND startDate < DATE '2015-02-01'
person Guffa    schedule 15.10.2015
comment
Буду признателен, если вы также упомянете, что ПОЧЕМУ здесь лучше использовать условие диапазон дат. По сути, речь идет о производительности, то есть об использовании B*Tree index (если есть). - person Lalit Kumar B; 15.10.2015
comment
Таким образом, это простое числовое сравнение вместо сопоставления текстового шаблона Нет, это неправда, это вовсе не числовое сравнение. В Oracle DATE и NUMBER совершенно разные». - person Lalit Kumar B; 15.10.2015
comment
Я ценю это. Но, пожалуйста, замените числовое сравнение сравнением даты, так как оно более уместно. Дата отличается от числовой (число в оракуле). - person Lalit Kumar B; 15.10.2015
comment
@LalitKumarB: дата хранится в виде набора числовых компонентов, поэтому сравнение дат выполняется путем числового сравнения соответствующих числовых компонентов. Я не понимаю, как числовые сравнения были бы неуместны. - person Guffa; 15.10.2015
comment
Пожалуйста, предоставьте ссылку на официальную документацию Oracle, где вы это прочитали. Oracle хранит дату во внутреннем формате в 7 байт. И внутренний формат никоим образом не является числовым. Таким образом, просто сказать, что дата в оракуле сравнивается с числовой, безосновательно. Между прочим, я видел несколько разработчиков SQL Server, говорящих такие вещи. То же самое и с вами? - person Lalit Kumar B; 15.10.2015
comment
@LalitKumarB: Интересно, что вы думаете о байтах? Когда база данных сравнивает эти значения байтов, думаете ли вы, что она использует какой-либо другой способ, кроме числового сравнения? - person Guffa; 15.10.2015
comment
Лалит прав, сравнение дат обрабатывается иначе, чем числовое сравнение. Тем не менее, я понимаю, что вы пытаетесь сказать, Гуффа - фактически сравнение носит числовой характер, и полезно думать о них таким образом (т. е. каждое значение даты представляет определенный момент времени для ближайшую секунду, и может рассматриваться как количество секунд после определенной эпохи — вот почему мы можем сравнивать даты, вычитать одну из другой и добавлять к ним числовые значения). - person Jeffrey Kemp; 16.10.2015
comment
@JeffreyKemp: Естественно, сравнение дат обрабатывается иначе, чем сравнение типа данных Number, но я никогда не говорил, что даты сравниваются как значения Number, я сказал, что сравнение является числовым. - person Guffa; 16.10.2015
comment
Возможно, мы все говорим об одном и том же, но интерпретируем по-разному. Думаю, мы помогли ОП с тем, что он хотел. - person Lalit Kumar B; 16.10.2015

Если тип поля "ДАТА", то значение не сохраняется в виде строки, это число, которым управляет 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');
person mbk    schedule 15.10.2015
comment
Сначала прочитайте о неявных преобразованиях данных: здесь docs.oracle .com/cd/E11882_01/server.112/e41084/ В этом случае Oracle автоматически преобразует дату в varchar, ваш ответ не точен. - person krokodilko; 15.10.2015
comment
to_char() является явным: docs.oracle.com/ cd/E11882_01/server.112/e41084/ - person mbk; 15.10.2015

Что касается вашего фактического вопроса: «Как-то это не работает, и я не знаю, почему».

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

person Wernfried Domscheit    schedule 15.10.2015

Данные в этом столбце хранятся в формате дд.мм.гггг.

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

ГДЕ startDate как "% 01.2015"

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

С точки зрения производительности следует использовать условие диапазона дат, чтобы, если в столбце дат есть обычный ИНДЕКС, он был использовал.

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

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

person Lalit Kumar B    schedule 15.10.2015

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

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 + "%'";
person Eronildo Barbosa    schedule 24.02.2017

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

В Oracle столбец типа «дата» не является ни числом, ни строкой, это значение «дата-время» с годом, месяцем, днем, часом, минутой и секундами. Время по умолчанию всегда полночь "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')
person alvalongo    schedule 25.01.2018
comment
Запрос представляет собой строку, созданную внутри C#, поэтому необходимы начальная и последняя кавычки. - person alvalongo; 26.01.2018

SELECT * FROM myTab WHERE startDate like '%-%-2015';

Это будет искать все даты в 2015 году. Если это не сработает, попробуйте:

SELECT * FROM myTab WHERE startDate like '%-%-15';
person Steven Toyama    schedule 04.05.2020

person    schedule
comment
Ваш способ вроде сработал. Теперь у меня проблема, что другие даты не работают. Если я попытаюсь использовать «% 01.2013», я не получу никаких данных, но я знаю, что в этом диапазоне есть даты... - person Mihawk; 15.10.2015
comment
@ Лалит, могу я скромно предложить тебе немного смягчить тон? Этот ответ не совсем неправильный, он просто не лучший. На самом деле, этот ответ будет работать, хотя есть гораздо лучшие способы решения проблемы, и на самом деле не полагается на неявное преобразование типа данных. - person Jeffrey Kemp; 16.10.2015
comment
@Джеффри, достаточно честно :-) - person Lalit Kumar B; 16.10.2015