2015-10-15 11 views
5

La mia tabella myTab ha la colonna startDate, che ha il tipo di dati "DATA". I dati in questa colonna sono memorizzati come dd.mm.yyyy.Oracle utilizza LIKE '%' su DATE

Ora sto cercando di ottenere i dati con questa query:

SELECT * FROM myTab WHERE startDate like '%01.2015" 

In qualche modo non funziona e non so perché.

Spero che qualcuno possa aiutare.

+0

Se si desidera che tutte le righe nel gennaio 2015 l'uso 'dove to_char (startDate, 'Mon-YYYY') = 'gen- 2015 '; ' – Mihai

+0

Dai un'occhiata a [Confronto Oracle Oracle di DATE restituisce risultati errati] (http://stackoverflow.com/questions/29005398/oracle-sql-comparison-of-dates-returns-wrong-result/29005418# 29005418) –

risposta

18

Per effettuare una ricerca di testo sulla data, è necessario convertire la data in testo.

È più efficiente se si calcola la prima e l'ultima data per ciò che si desidera trovare e ottenere tutto tra di loro. In questo modo è fatto come i confronti numerici al posto di un pattern match di testo, e si può fare uso di un indice, se ce n'è uno:

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

Ti sarei grato se tu menzioni anche questo ** PERCHÉ ** utilizzando un ** intervallo di date ** la condizione è migliore qui. Fondamentalmente, si tratta di prestazioni, ad esempio l'uso di un indice B * Tree * (se presente). –

+0

@LalitKumarB: buon punto. – Guffa

+0

"* In questo modo si tratta di un semplice confronto numerico anziché di una corrispondenza del modello di testo *" No, non è vero, non è affatto un confronto numerico. In Oracle, ** DATA ** e ** NUMERO ** sono completamente diversi. ' –

2

Se il campo è di tipo "DATA", allora il valore non viene memorizzato come una stringa, si tratta di un numero gestito da Oracle, in modo da avere per convertirlo in una stringa:

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

è inoltre possibile utilizzare intervalli di date nelle query 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

Leggere prima le conversioni implicite dei dati: http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements002.htm # i53062 Oracle converte automaticamente una data in varchar in questo caso, la tua risposta non è precisa .. – krokodilko

+0

to_char() è esplicito: 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

Il tuo modo ha funzionato. Ora ho il problema che altre date non funzionano. Se provo a utilizzare '% 01.2013' non ottengo alcun dato ma so che ci sono date in questo intervallo ... – Ovoxo

+0

@Lalit, posso umilmente suggerire di rilassare un po 'il tono? Questa risposta non è "completamente sbagliata", non è solo la migliore. In effetti, questa risposta * funzionerà *, sebbene ci siano molti modi migliori per risolvere il problema, e * non *, in effetti, si basano sulla conversione implicita del tipo di dati. –

+0

@Jeffrey, abbastanza corretto :-) –

1

Per quanto riguarda la domanda attuale "In qualche modo non funziona e non so perché."

Oracle effettua una conversione implicita da DATE a VARHCAR2, tuttavia utilizza il valore predefinito NLS_DATE_FORMAT che è probabilmente diverso da quello che si utilizza nella query.

1

I dati in questa colonna sono memorizzati come gg.mm.aaaa.

Oracle non memorizza la data nel formato visualizzato. Lo memorizza internamente in formato proprietario in 7 byte con ogni byte che memorizza componenti diversi del valore datetime.

DOVE startDate come '% 01,2015"

si sta confrontando un DATA con un STRING, che è inutile.

Da punto di vista delle prestazioni, si dovrebbe utilizzare una condizione di intervallo di date in modo che se ci sono regolari INDICE nella colonna di date umn, sarebbe usato.

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

Per capire perché una serie Data condizione è migliore in termini di prestazioni , dare un'occhiata alla mia risposta here.

0

Ho risolto il mio problema in questo modo. Grazie per i suggerimenti per i miglioramenti. Esempio 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 + "%'"; 
0

di fornire una risposta più dettagliata e affrontare problema questo https://stackoverflow.com/a/42429550/1267661 di risposta.

In Oracle una colonna di tipo "data" non è un numero né una stringa, è un valore "datetime" con anno, mese, giorno, ora, minuto e secondi. Il tempo di default è sempre la mezzanotte "00:00:00"

La query:

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

non funziona in tutte le circostanze, perché una colonna di data non è una stringa, utilizzando "come" forze Oracle fare una conversione dal valore data al valore stringa. Il valore stringa può essere anno-mese-giorno-ora o mese-giorno-anno-anno o giorno-mese-anno-tempo, tutto dipende da come una particolare istanza Oracle ha impostato il parametro NLS_DATE_FORMAT per mostrare le date come stringhe.

Il modo giusto per coprire tutte le possibili volte in un giorno è:

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

La query è una stringa costruita all'interno di C#, quindi è necessario il preventivo iniziale e l'ultima citazione – alvalongo