Проверка членства в массиве в DB2 SQL PL
Я перенес код хранимой процедуры из Oracle в DB2, и мне нужно найти способ проверить членство в массиве (Oracle имеет MEMBER OF
оператор).
Хранимая процедура использует, помимо прочего, массив пользователей (полученный в качестве параметра из кода Java через JDBC). Я хочу найти наиболее эффективный способ сделать тест членства в этом массиве. Используя Oracle, я бы сделал:
FOR r IN (SELECT * FROM acls WHERE acls.id = curid) LOOP
IF r.user MEMBER OF users THEN
RETURN 1;
END IF;
END LOOP;
Однако я не нахожу эквивалента MEMBER OF
в DB2:
FOR r AS SELECT * FROM acls WHERE acls.id = curid DO
IF r.user ????? users THEN
RETURN 1;
END IF;
END FOR;
Я вижу две альтернативы:
- сделать еще один внутренний цикл для всех элементов массива, чтобы выполнить тест "вручную".
- не используйте массив, а одну строку и используйте
LIKE
сопоставление с образцом
Есть ли способ лучше? Пожалуйста, имейте в виду, что массив взят из внешнего кода и не может быть передан как таблица, к которой я мог бы JOIN
или что-нибудь связанное.
1 ответ
Вы можете сделать это с помощью ассоциативного массива (доступно в DB2 9.7+) и array_exists
предикат Я не уверен, что это будет работать с тем, что передается в процедуру.
Тем не менее, я нашел array_exists
быть довольно медленным Ваш общий дизайн цикла с курсором также будет очень медленным.
Если производительность является проблемой, вам, скорее всего, лучше сделать одну из следующих вещей:
- Закинуть массив пользователей во временную таблицу внутри процедуры, затем сделать нормальный
join
к этой таблице, чтобы найти соответствующие записи. - Используйте динамический SQL для создания запроса (например, внутри
in
пункт.
Вот пример того, что вы могли бы сделать с динамическим SQL. Для этого решения Java отправит вам одну строку, разделенную запятыми:
declare v_sql varchar(1000); --Bigger than maximum possible result query...
declare stmt varchar(1000);
declare return_result integer;
set v_sql = 'select case when count(*) > 0 then 1 else 0 end' &
' from acls WHERE acls.id = curid and user in (' & users & ')' &
' group by (1)';
prepare stmt from v_sql;
open mycur;
fetch mycur into return_result;
close mycur;
return return_result;
Это предполагает, что пользователи имеют числовые значения. Если они являются строками, это не будет работать, потому что каждый пользователь должен быть указан в in
пункт.