вторник, декабря 09, 2008

Параметризованый SQL: способы параметризации IN

Первый раз проблема параметризации IN встала передо мной сразу после того как я узнал про связываемые переменные. Тогда я проигнорировал проблему, но сейчас решил к ней вернуться.

Первый способ. Декларативный.
Состоит в том чтобы объявить переменные для максимального количества значений. Поскольку он очевиден, то думаю что подробнее на этом способе останавливаться не стоит.

SELECT * FROM TABLE1
WHERE FK_ID IN (:IN_P1, :IN_P2, :IN_P3, :IN_P4, :IN_P5);


Второй способ. Рекурсивный.
Реализуется с помощью иерархических (читай рекурсивных) запросов Oracle. Для реализации этого способа нам понадобятся функции INSTR и SUBSTR и, собственно иерархический запрос.
INSTR - функция возвращает позицию подстроки внутри строки

REGEXP_SUBSTR - возвращает подстроку соответствующую регулярному выражению. Функция regexp_substr появилась только в десятой версии оракла, в предыдущих нужно шаманить с функциями SUBSTR и INSTR.

Что такое иерархические запросы можно прочитать на хабре (на русском) и в документации (на английском)
Запрос принимает входящий параметр - строку со значениями разделенными запятой (или любым другим подходящим символом) и превращает его во вьюху состоящую из значений входящей строки. Из этой вьюхи берутся данные для оператора IN.
На практике это может выглядеть так:

SELECT * FROM TABLE1
WHERE FK_ID IN (select regexp_substr(:in_str, '[^,]+',1,level) FROM DUAL CONNECT BY INSTR(:in_str,',',1, level)>0
);

Строка :in_str обязательно должна заканчиваться запятой, иначе последний параметр в строке будет пропущен.

Сравнение двух способов
С точки зрения удобства первый способ менее удобен чем второй - это очевидно, а с точки оптимизатора запросов есть один ньюанс. При использовании декларативного способа оптимизатор точно знает сколько значений находится в IN и может раскрыть скобки: ... id in (:p1, :p2, :p3) id=:p1 or id=:p2 or id=:p3, а в случае с рекурсивным способом оптимизатор должен создать виртуальную таблицу и сделать inner join c основной таблицей. Стоит это учитывать.

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

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