четверг, 30 октября 2014 г.

Поучительная история про применение знаний.

Завел новый ярлык: "век живи - век учись". Причиной послужил следующий случай. Простая задачка: из смежной системы приходит идентификатор, по которому надо найти данные и добавить их в таблицу. База данных - Oracle. Казалось бы, что может быть проще. Есть, правда, одно отягчающее обстоятельство: приходит только идентификатор, а данные, которые он идентифицирует, могут лежать в одной из нескольких таблиц. Точнее, в одной из двух. То есть, указания, в какой таблице следует осуществлять поиск, нет. К счастью, идентификатор уникален, даже с учетом того факта, что исходных таблиц для поиска несколько - две.
Решений, как водится, может быть несколько. Без каких-либо задних мыслей было выбрано одно из - использовать объединение.

select src from
  (
    select src from tbl_out where id = hextoraw(:id)
    union
    select src from tbl_in where id = hextoraw(:id)
  )

Еще одно вводное условие: поле src в обеих таблицах - CLOB. Если после этого уточнения вы просекли фишку, идентифицировали проблему и знаете решение - примите мои уверения в совершеннейшем к вам почтении. И да, можете дальше не читать этот ламерский блог. Для всех остальных продолжу.

Запуск этой нехитрой конструкции приводит к возврату ошибки:

ORA-00932: inconsistent datatypes: expected - got CLOB

Особенно меня порадовал оборот речи "expected - got CLOB". Драку заказывали? А, все равно, уплачено... получите... CLOB.

Профессор, конечно, лопух, но кое-какая аппаратура, то бишь, знания, при нем. Я знаю, что такую ошибку можно получить, если поле CLOB сравнивать с чем-то в where части SQL запроса. Происходит это из-за того, что (далее цитата из документации):

Large objects (LOBs) are not supported in comparison conditions".

Однако знания надо еще и применять, иногда, творчески. И тут, я, конечно, дал маху. Ведь что есть union? Это объединение двух наборов за исключением дубликатов. И вот в этом исключении и кроется корень проблемы. Чтобы понять, что нужно исключить из объединения наборов, надо понять, что является дубликатами, а для этого, по всей видимости, приходится сравнивать данные, а сравнивать LOB-ы, как мы знаем, нельзя. Небезызвестный сайт Ask Tom еще более категоричен.

Там же, кстати, содержится и рекомендация, как обойти проблему. И, после разбора причин ошибки, становится ясно, что этот обходной маневр вполне применим для решаемой задачи. Ведь по условию задачи, идентификатор обладает уникальностью не только в рамках конкретной таблицы, он уникален для всех задействованных таблиц. А раз так, то дубликатов быть не может, и union all вполне себе замена для union. Получаем:

select src from
  (
    select src from tbl_out where id = hextoraw(:id)
    union all
    select src from tbl_in where id = hextoraw(:id)
  )

Этот запрос отрабатывает без малейших проблем. Вот такие вот дела.

Комментариев нет:

Отправить комментарий