Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Equals(=) vs. LIKE para o tipo de dados de data


Supondo LAST_TRANSACTION_DATE é uma DATE coluna (ou TIMESTAMP ) então ambas as versões são uma prática muito ruim.

Em ambos os casos, a DATE A coluna será convertida implicitamente em um literal de caractere com base nas configurações atuais de NLS. Isso significa que com clientes diferentes você obterá resultados diferentes.

Ao usar literais de data sempre use to_date() com(!) uma máscara de formato ou use um literal de data ANSI. Dessa forma, você compara datas com datas e não strings com strings. Então, para a comparação igual, você deve usar:
LAST_TRANSACTION_DATE = to_date('30-JUL-07', 'dd-mon-yy')

Observe que o uso de 'MON' ainda pode levar a erros com diferentes configurações de NLS ('DEC' vs. 'DEZ' ou 'MAR' vs. 'MRZ' ). É muito menos propenso a erros usando números de meses (e anos de quatro dígitos):
LAST_TRANSACTION_DATE = to_date('30-07-2007', 'dd-mm-yyyy')

ou usando um literal de data ANSI
LAST_TRANSACTION_DATE = DATE '2007-07-30'

Agora, a razão pela qual a consulta acima provavelmente não retornará nada é que no Oracle DATE colunas incluem o tempo também. Os literais de data acima contêm implicitamente a hora 00:00 . Se a hora na tabela for diferente (por exemplo, 19:54 ) então é claro que as datas não são iguais.

Para contornar esse problema, você tem diferentes opções:
  1. use trunc() na coluna da tabela para "normalizar" o tempo para 00:00 trunc(LAST_TRANSACTION_DATE) = DATE '2007-07-30 no entanto, isso impedirá o uso de um índice definido em LAST_TRANSACTION_DATE
  2. use between
    LAST_TRANSACTION_DATE between to_date('2007-07-30 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and to_date('2007-07-30 23:59:59', 'yyyy-mm-dd hh24:mi:ss')

O problema de desempenho da primeira solução pode ser contornado criando um índice em trunc(LAST_TRANSACTION_DATE) que poderia ser usado por essa expressão. Mas a expressão LAST_TRANSACTION_DATE = '30-JUL-07' impede o uso de um índice também porque internamente ele é processado como to_char(LAST_TRANSACTION_DATE) = '30-JUL-07'

As coisas importantes a serem lembradas:
  1. Nunca, nunca confie na conversão implícita de tipo de dados. Ele vai dar-lhe problemas em algum momento. Sempre compare os tipos de dados corretos
  2. Oracle DATE as colunas sempre contêm uma hora que faz parte das regras de comparação.