Как решить ошибку этого выбора записи в оракуле? - PullRequest
0 голосов
/ 14 января 2019

Я хочу сделать выбор в диапазоне от 01.06.2009 до 01.09.2009, но программа возвращает другие диапазоны, например, показать изображение.

Помните, что мое поле даты в базе данных varchar2, и я храню его в формате дд / мм / гггг

image

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Расширяя ответ @ user7294900, поскольку вы сохраняете значение 'date' в виде строки, вам необходимо преобразовать как значение столбца, так и значения целевого диапазона из строк в фактические даты.

Если вы делаете:

WHERE DATA_TRANSACAO BETWEEN '06/01/2019' AND '09/01/2019'

тогда вы выполняете сравнение строк между значением столбца и этими литералами, а в виде строки все, что начинается с '07' или '08' (и большинство начинается с '06'), будет считаться частью из этого диапазона. Oracle рассматривает их исключительно как строки, не знает или не заботится о том, что у вас есть представление о днях и месяцах или что вы считаете, что заказ отличается от других.

Если вы действительно застряли со строками, то вам нужно сравнить обе стороны сравнения с датами:

WHERE TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') BETWEEN TO_DATE('06/01/2019', 'DD/MM/YYYY')
  AND TO_DATE('09/01/2019', 'DD/MM/YYYY')

или с литералами ANSI:

WHERE TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') BETWEEN DATE '2019-06-01' AND DATE '2019-01-09'

или (хотя это более полезно, если может быть не полночь, что не соответствует вашим данным):

WHERE TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') >= DATE '2019-06-01'
AND TO_DATE(DATA_TRANSACAO, 'DD/MM/YYYY') < DATE '2019-01-10' -- notice one day later

Вы также должны знать, что необходимость преобразования строкового значения для каждой строки в ваших данных перед тем, как вы сможете их сравнить, означает, что если у вас есть простой индекс для этого столбца, его нельзя использовать, и полное сканирование таблицы будет выполнено даже для небольшого целевого диапазона дат. (Вы можете добавить индекс на основе функций, чтобы ускорить это, но это гипсовый подход.)

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

Я действительно рекомендую вам пересмотреть модель данных и перейти от отдельных строк для DATA_TRANSACAO и HORA_TRANSACAO к одному столбцу DATE, который содержит целое значение даты / времени в качестве правильного типа данных. После этого вы сможете использовать более простую форму, без преобразования данных вашей таблицы, что-то вроде (с вымышленным объединенным именем столбца):

WHERE DATAHORA_TRANSACAO >= DATE '2019-06-01'
AND DATAHORA_TRANSACAO < DATE '2019-01-10' -- notice one day later
0 голосов
/ 14 января 2019

Если вы ожидаете, что значения 06/08 будут представлять дни, будьте явными:

BETWEEN TO_DATE('06/01/2019','DD/MM/YYYY')
AND TO_DATE('09/01/2019','DD/MM/YYYY')

В настоящее время он возвращает значения 06/08 в виде месяцев. Обычно при сравнении столбца даты используется даты, а не строки

Я настоятельно рекомендую вам использовать to_date, чтобы избежать двусмысленности (сравнивайте строки со строками, числами с числами, датами и датами - не рискуйте путать сравнение строк с числами, дат со строками).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...