Почему результаты запроса изменяются при использовании coalesce для поля char в предложении where? - PullRequest
4 голосов
/ 29 мая 2019

Я наблюдаю неожиданное поведение при запросе с предложением where для объединенного поля char в базе данных Oracle.

Кажется, что результаты

CASE WHEN COALESCE(char_field, 'some_val') = 'someOtherVal'

отличаются отрезультаты

CASE WHEN char_field = 'someOtherVal'

Конкретные сравнения, в которых я заметил этот странный вывод: «между», «в» и «равно».Вот странные выходные данные, которые я вижу:

  1. Между верхними границами, кажется, не учитывается
  2. In и равно false для каждого сравнения

Вот некоторые sql для репликации странности:

CREATE TABLE delete_me( some_char CHAR(8) );

INSERT ALL   
  INTO delete_me (some_char) VALUES ('1')
  INTO delete_me (some_char) VALUES ('2')
  INTO delete_me (some_char) VALUES ('4')
  INTO delete_me (some_char) VALUES ('5')
  INTO delete_me (some_char) VALUES ('abc1')
  INTO delete_me (some_char) VALUES (null)
SELECT 1 FROM DUAL;

SELECT some_char,
  COALESCE(some_char, 'wasNull') AS coalesce_some_char,
  CASE
    WHEN (some_char BETWEEN '1' AND '5')
    THEN 'true'
    ELSE 'false'
  END AS between_1_5,
  CASE
    WHEN (COALESCE(some_char, 'wasNull') BETWEEN '1' AND '5')
    THEN 'true'
    ELSE 'false'
  END AS coalesce_between_1_5,
  CASE
    WHEN (some_char IN ('1', '5'))
    THEN 'true'
    ELSE 'false'
  END AS in_1_5,
  CASE
    WHEN (COALESCE(some_char, 'wasNull') IN ('1', '5'))
    THEN 'true'
    ELSE 'false'
  END AS coalesce_in_1_5,
  CASE
    WHEN (some_char = 'abc1')
    THEN 'true'
    ELSE 'false'
  END AS equals_abc1,
  CASE
    WHEN (COALESCE(some_char, 'wasNull') = 'abc1')
    THEN 'true'
    ELSE 'false'
  END AS coalesce_equals_abc1
FROM delete_me;

Я бы ожидал, что результаты сравнений для объединенных полей будут совпадать с результатами сравнения для неалесцентных полей для всех операторов, кроме IS NULL.

Кто-нибудь знает, почему эти результаты не совпадают?

1 Ответ

4 голосов
/ 29 мая 2019

Ваша проблема в типе данных some_char.Когда столбец типа CHAR сравнивается со строкой, пустой бланк Oracle дополняет строку до длины столбца (см. документы ).В тестах, которые вы выполняете, значения совпадают по длине ('1' против '1') или полностью отличаются ('1' против 'abc1'), поэтому все работает нормально.Однако, когда вы используете COALESCE в поле CHAR, выводом COALESCE является полностью пустое значение столбца с добавлением , возвращаемое как VARCHAR (см. Документы для NVL ) и поэтому строка сравнения не заполнена пробелом, и вы сравниваете '1 ' против '1', что не удается.Есть несколько способов обойти это.Вы можете TRIM вывод COALESCE т.е.

TRIM(COALESCE(some_char, 'wasNull'))

или изменить тип данных с some_char на VARCHAR(8) вместо этого.

Я сделал демонстрацию всехэто на dbfiddle

...