Как передать более одной строки в переменной связывания в столбце формулы отчета Oracle?

У нас есть страница, на которой отображается список записей, и пользователю разрешено проверять нужные строки, а затем распечатывать отчет по этим выбранным записям. Я пытаюсь определить отчет Oracle с одним параметром, который будет списком идентификаторов, разделенных запятыми, для печати. Однако это не работает. SQL примерно такой:

Select * from CEP_TABLE where Table_ID in (:P_IDLIST) 

Если я определяю параметр как числовой, я получаю ошибку «недопустимый ввод параметра» при попытке дать ему 654 655 — запятая не нравится.

Если я определяю параметр как символ, он принимает параметр, но затем база данных выдает ошибку «неверный номер». Похоже, что он заменяет переменную связывания всем параметром в кавычках — например.

Select * from CEP_TABLE where Table_ID in (‘654,655’)

Но я хочу без кавычек:

Select * from CEP_TABLE where Table_ID in (654,655)

Я могу заставить отчет работать, если я определяю несколько параметров, например. Table_ID в (:P1,:P2,:P3,:P4), но у них может быть сотня элементов, которые они хотят включить, поэтому определение 100 параметров кажется безумием — и на самом деле… я не хочу никаких ограничений.

Кто-нибудь уже решал эту проблему? - кажется, это было бы довольно обычно. Я мог бы заставить страницу записать выбранные идентификаторы во временную таблицу, а затем определить запрос для присоединения к этой таблице, но это также кажется чрезмерным.


person tanayals    schedule 02.10.2018    source источник
comment
Вы должны преобразовать свою строку в таблицу, чтобы использовать ее в sql. Посмотрите здесь, как это можно сделать: stackoverflow.com/questions/3142665/   -  person Radagast81    schedule 02.10.2018
comment
Возможно ли, чтобы отчеты превратили список отмеченных идентификаторов в набор чисел (например, sys.odcinumberlist), а не в строку, в которой они объединены вместе?   -  person Alex Poole    schedule 02.10.2018
comment
Oracle Reports позволяет использовать только базовые типы данных в качестве входных параметров, поэтому передача строки csv абсолютно уместна. Единственный другой способ - использовать временную таблицу, как описано...   -  person Radagast81    schedule 02.10.2018


Ответы (2)


На помощь приходит герой, и его зовут лексический параметр.

Вы сказали, что ваш запрос выглядит так:

select * 
from CEP_TABLE 
where Table_ID in (:P_IDLIST) 

Отчет уже содержит параметр с именем p_idlist. Теперь создайте еще один вручную; назовем его lex_idlist. Его тип данных должен быть character, его длина несколько больше, чем у параметра p_idlist (например, если p_idlist равно character(50), сделайте lex_idlist character(70)).

Затем перепишите запрос следующим образом:

select *
from cep_table
&lex_idlist

Перейдите к триггеру After Parameter Form, который должен выглядеть следующим образом:

function AfterPForm return boolean is
begin
  :lex_idlist := 'where table_id in (' || :p_idlist || ')';
  return (TRUE);
end;

Вот и все — скомпилируйте отчет и запустите его. Введите некоторые значения в параметр p_idlist (например, 654,655). Триггер динамически создаст предложение WHERE, сохранит его в лексическом параметре, который затем будет "действовать", как если бы это было настоящее предложение WHERE.

Узнайте больше о лексических параметрах в интерактивной справочной системе отчетов.

person Littlefoot    schedule 02.10.2018
comment
Я удовлетворен ответом. - person tanayals; 03.10.2018

Это очень распространенный и нетривиальный вопрос.

Вам нужно разбить одну входную строку на составляющие ее токены. Поскольку у меня нет вашей таблицы, я проиллюстрирую, как это делается на таблице emp в стандартной схеме scott; вот как вы можете получить строки для списка номеров отделов, указанных в одной строке, разделенной запятыми, например '10,30':

select * from scott.emp
where  deptno in 
    (select to_number(regexp_substr(:p_deptno, '\d+', 1, level)) from dual
       connect by level <= regexp_count(:p_deptno, '\d+')
    )
;

Справедливости ради, есть также методы, которые не разбивают строку, а вместо этого играют в глупые игры со сравнением строк; но они будут совершенно неэффективны - например, они не позволят вам использовать индекс, который у вас может быть на table_id (или на deptno в моем примере).

person mathguy    schedule 02.10.2018