Может ли expressionList оператора SELECT ... WHERE IN (expressionList) быть переменной? - PullRequest
1 голос
/ 23 октября 2019

Следующий код создает фильтр, который я успешно добавляю к существующему оператору sql.

DECLARE V_FILTER VARCHAR2(255);
begin
SELECT DISTINCT 'reserve reporting_unit_code' ||' IN (' || 
                listagg ( chr(39) ||  uic || chr(39) , ',') within group (order by uic) || ')'  
into v_FILTER               
from ( select distinct uicf.uic           
        FROM OWSADHOC.ADHOC_UIC_FILTER UICF
                 INNER JOIN OWSADHOC.ADHOC_USER_ROLE  UROLE
                    ON UICF.ROLE_NAME = UROLE.ROLE_NAME
                 inner join OWSADHOC.ADHOC_USER_DATA uname
                    on uname.USER_ID = UROLE.USER_ID
        WHERE UROLE.ROLE_NAME in (:P_LoggedInUserRoles)  
         and  uname.JASPER_ACCOUNT = :P_LoggedInUserName
         )
      ;   
      DBMS_OUTPUT.PUT_LINE ('GENERATED FILTER: ' || V_FILTER); 
      end;

v_FILTER равно reserve reporting_unit_code IN ('86749')

Это прекрасно работает, когда P_LoggedInUserRoles имеет толькоодно значениеОднако, если у меня есть список в переменной, разделенный запятыми, он не работает. Я попытался определить expressionList как массив. PL / SQL не компилируется с использованием этого метода.

Ограничен ли expressionList использованием литеральных значений, если имеется более одного значения? Я не могу найти это явное утверждение ни в одном руководстве, но я не смог определить expressionList как переменную, которая представляет собой набор значений.

1 Ответ

1 голос
/ 23 октября 2019

Нет, вы не можете, но вы достаточно близки

Список, разделенный запятыми, заставит условие выглядеть так:

WHERE UROLE.ROLE_NAME in ('Jane, Andrew, Jill')

и вернетпустой набор результатов. В то время как вы ищете

WHERE UROLE.ROLE_NAME in ('Jane', 'Andrew', 'Jill')

Совершенно очевидно, что число переменных связывания должно будет отличаться от одного вызова к другому, поскольку списки имеют разную длину. Извините, это не то, что мы можем сделать легко. Вам нужно что-то под названием Метод динамического SQL 4 , и это кажется излишним.


Хотя есть более простой способ. Мы собираемся проанализировать входную строку значений, разделенных запятыми, в набор результатов. Мы собираемся сделать это в подзапросе, и мы можем использовать подзапросы в IN.

Вот как мы это делаем

WHERE UROLE.ROLE_NAME in (
  SELECT NAME
  FROM (
    SELECT regexp_substr(:P_LoggedInUserRoles, '(.*?)(,|$)', 1, LEVEL, null, 1) NAME, LEVEL LVL
    FROM   DUAL
    CONNECT BY LEVEL <= regexp_count(:P_LoggedInUserRoles, ',') + 1)
  ORDER BY LVL)

Я бесстыдно украл регулярное выражениеиз этого вопроса: Oracle - разделенная запятая строка с разделителями (строка содержит пробелы и последовательные запятые) , так что вы можете пойти дальше и получить ответ там.

Теперь недостатком, конечно, является то, чтомы будем делать этот CONNECT BY трюк все время, даже если мы получим одно имя, но это тема для другого времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...