Проверка членства в массиве в 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;

Я вижу две альтернативы:

  1. сделать еще один внутренний цикл для всех элементов массива, чтобы выполнить тест "вручную".
  2. не используйте массив, а одну строку и используйте 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 пункт.

Другие вопросы по тегам