Основная проблема не в функции listagg, а в серьезном заблуждении, что только потому, что элементы в списке строк разделены запятыми, строка с запятыми в ней является списком.Не так.Рассмотрим таблицу со следующими строками.
Ключ
- Данные1
- Данные2
- Данные1, Данные2
И запрос: Выбрать * из таблицы_имя, где ключ = 'wanted_key';Теперь, если все запятые разделяют независимые элементы, то какое значение для "wanted_Key" необходимо для возврата только 3-й строки выше?Даже с предикатом IN 'Data1, Data2' по-прежнему всего 1 значение, а не 2. Для 2 значений это должно быть ('Data1', 'Data2').
Проблема, с которой вы сталкиваетесь в Listagg, не в запятой, а в том, что она не подходит.Listagg берет значения из нескольких строк и объединяет их в одну строку, разделенную запятыми, но не список, разделенный запятыми.Пример:
with elements as
( select 'A' code, 'Data1' item from dual union all
select 'A', 'Data2' from dual union all
select 'A', 'Data3' from dual
)
select listagg( item, ',') within group (order by item)
from elements group by code;
(Возможно, вы также захотите попробовать 'Data1, Data2' как отдельный элемент. Осторожно.
Вам требуется запрос, который разбивает каждыйэлемент по отдельности. Это можно сделать с помощью
with element_list as
(select 'Data1,Data2,Data3' items from dual) -- get paraemter string
, parsed as
(select regexp_substr(items,'[^,]+',1,level) item
from element_list connect by regexp_substr(items,'[^,]+',1,level) is not null -- parse string to elements
)
CTE "parsed" теперь можно использовать как таблицу / представление в вашем запросе.
Это не будет работать так же, как запрос непосредственно с параметром,но снижение производительности - это стоимость динамических / гибких запросов.
Кроме того, при настройке это НЕ будет обрабатывать параметры, которые содержат запятые в отдельном элементе. Это потребовало бы гораздо больше кода, поскольку вы должны были бы определить / спроектировать, как сохранитьзапятая в этих элементах.