arraysdb2sql-pl

Testing array membership in DB2 SQL PL


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:

  1. do another inner loop an all array elements to do the test "by hand".
  2. don't use an array but a single string and use 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.


Solution

  • 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:

    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.