-->

Oracle use LIKE '%' on DATE

2019-02-22 09:35发布

问题:

My table myTab has the column startDate, which has the datatype "DATE". The data in this column are stored like dd.mm.yyyy.

Now I'm trying to get data with this query:

SELECT * FROM myTab WHERE startDate like '%01.2015"

Somehow it doesn't work and I don't know why.

Hope someone can help.

回答1:

To make a text search on the date you would have to convert the date to text.

It's more efficient if you calculate the first and last date for what you want to find and get everything between them. That way it's done as numeric comparisons instead of a text pattern match, and it can make use of an index if there is one:

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


回答2:

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


回答3:

If the field type is "DATE" then the value isn't stored as a string, it's a number managed by Oracle, so you have to convert it to a string:

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

You can also use date ranges in SQL queries:

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


回答4:

Regarding you actual question "Somehow it doesn't work and I don't know why."

Oracle make an implicit conversion from DATE to VARHCAR2, however it uses the default NLS_DATE_FORMAT which is probably different to what you use in your query.



回答5:

The data in this column are stored like dd.mm.yyyy.

Oracle does not store date in the format you see. It stores it internally in proprietary format in 7 bytes with each byte storing different components of the datetime value.

WHERE startDate like '%01.2015"

You are comparing a DATE with a STRING, which is pointless.

From performance point of view, you should use a date range condition so that if there is any regular INDEX on the date column, it would be used.

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

To understand why a Date range condition is better in terms of performance, have a look at my answer here.



回答6:

I solved my problem that way. Thank you for suggestions for improvements. Example in 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 + "%'";


回答7:

To provide a more detailed answer and address this https://stackoverflow.com/a/42429550/1267661 answer's issue.

In Oracle a column of type "date" is not a number nor a string, it's a "datetime" value with year, month, day, hour, minute and seconds. The default time is always midnight "00:00:00"

The query:

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

won't work in all circumstances because a date column is not a string, using "like" forces Oracle to do a conversion from date value to string value. The string value may be year-month-day-time or month-day-year-time or day-month-year-time, that all depends how a particular Oracle instance has set the parameter NLS_DATE_FORMAT to show dates as strings.

The right way to cover all the possible times in a day is:

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