I'm migrating stored procedure code from Oracle to DB2 and I need to find a way to test array membership (Oracle has a MEMBER OF
operator).
The stored procedure uses among other things an array of users (received as a parameter from Java code, through JDBC). I want to find the most efficient way to do membership test in that array. Using Oracle, I would do:
FOR r IN (SELECT * FROM acls WHERE acls.id = curid) LOOP
IF r.user MEMBER OF users THEN
RETURN 1;
END IF;
END LOOP;
However I don't find an equivalent of MEMBER OF
in DB2:
FOR r AS SELECT * FROM acls WHERE acls.id = curid DO
IF r.user ????? users THEN
RETURN 1;
END IF;
END FOR;
I see two alternatives:
LIKE
-based pattern matching.Is there a better way? Please keep in mind that the array comes from external code and cannot be passed as a table to which I could JOIN
or anything related.
You can do this with an associative array (available in DB2 9.7+) and the array_exists
predicate. I'm not sure whether that would be workable with what is being passed into the procedure.
However, I found array_exists
to be quite slow. Your general design of looping with a cursor will also be very slow.
If performance is a concern, you are likely to be better off doing one of these things instead:
join
to that table to find the matching records.in
clause.Here is an example of something you could do with dynamic SQL. For this solution, have Java send you a single string, separated by commas:
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;
This assumes the users are numeric values. If they are strings, it wouldn't work because each user has to be quoted in the in
clause.