Ограничения оператора in () - корень всего зла.
Это работает для тривиальных случаев, и вы можете расширить его с помощью «автоматической генерации подготовленного оператора», однако оно всегда имеет свои пределы.
- если вы создаете оператор с переменным числом параметров, это приведет к дополнительным затратам на анализ SQL при каждом вызове
- на многих платформах количество параметров оператора in () ограничено
- на всех платформах, общий размер текста SQL ограничен, что делает невозможным отправку 2000 заполнителей для параметров in
- отправка переменных связывания 1000-10k невозможна, поскольку драйвер JDBC имеет свои ограничения
Подход in () может быть достаточно хорош для некоторых случаев, но не является надежным:)
Ракетно-стойким решением является передача произвольного количества параметров в отдельном вызове (например, путем передачи сгустка параметров), а затем представление (или любой другой способ) для представления их в SQL и использования в ваших критериях где.
Вариант грубой силы здесь http://tkyte.blogspot.hu/2006/06/varying-in-lists.html
Однако, если вы можете использовать PL / SQL, этот беспорядок может стать довольно аккуратным.
function getCustomers(in_customerIdList clob) return sys_refcursor is
begin
aux_in_list.parse(in_customerIdList);
open res for
select *
from customer c,
in_list v
where c.customer_id=v.token;
return res;
end;
Затем в параметре можно передать произвольное количество идентификаторов клиентов, разделенных запятыми, и:
- не получит задержки разбора, поскольку SQL для выбора стабилен
- нет сложности с конвейерными функциями - это всего лишь один запрос
- SQL использует простое соединение вместо оператора IN, что довольно быстро
- В конце концов, это хорошее эмпирическое правило: , а не , воздействовать на базу данных любым простым выбором или DML, поскольку это Oracle, который предлагает световые годы больше, чем MySQL или аналогичные простые движки баз данных. PL / SQL позволяет эффективно скрывать модель хранения от модели предметной области вашего приложения.
Хитрость здесь в следующем:
- нам нужен вызов, который принимает длинную строку и сохраняет где-то, где сессия db может получить к ней доступ (например, простая переменная пакета или dbms_session.set_context)
- тогда нам нужно представление, которое может разобрать это по строкам
- и затем у вас есть представление, содержащее идентификаторы, которые вы запрашиваете, поэтому все, что вам нужно, - это простое соединение с запрашиваемой таблицей.
Вид выглядит так:
create or replace view in_list
as
select
trim( substr (txt,
instr (txt, ',', 1, level ) + 1,
instr (txt, ',', 1, level+1)
- instr (txt, ',', 1, level) -1 ) ) as token
from (select ','||aux_in_list.getpayload||',' txt from dual)
connect by level <= length(aux_in_list.getpayload)-length(replace(aux_in_list.getpayload,',',''))+1
где aux_in_list.getpayload ссылается на исходную строку ввода.
Возможным подходом было бы передать массивы pl / sql (поддерживаемые только Oracle), однако вы не можете использовать их в чистом SQL, поэтому всегда необходим шаг преобразования. Преобразование не может быть выполнено в SQL, поэтому, в конце концов, передача clob со всеми параметрами в строке и преобразование его в представление является наиболее эффективным решением.