Функция LISTAGG возвращает крякозабры

Есть данные:

id type
1 а
1 б
1 с
2 д

Так все отображается правильно:

SELECT * FROM t1

Но если использую функцию LISTAGG, то вижу непонятные квадратики вместо кириллицы:

SELECT 
ID, LISTAGG(TYPE, '; ') WITHIN GROUP (ORDER BY ID) "product_listing"
FROM t1
GROUP BY ID

Например, вместо слова "Аренда" я вижу символы: @5=40

Из-за чего это происходит и как это исправить?

При чем, я заметила, что если я сама задаю значение, например:

with t1 as (
select 1 as id, 'х' as type from dual
union all
select 1 as id, 'Аренда' as type from dual
union all
select 1 as id, 'y' as type from dual
union all
select 2 as id, 'z' as type from dual
) 
SELECT ID, LISTAGG(TYPE, '; ') WITHIN GROUP (ORDER BY ID) "product_listing"
FROM t1
GROUP BY ID

, то все будет отображаться правильно.


Ответы (1 шт):

Автор решения: 0xdb

Решение: явно конвертировать функцией TO_CHAR символы юникодов из кодировки AL16UTF16 в кодировку БД (в вопросе CL8MSWIN1251):

SELECT ID, LISTAGG (TO_CHAR (TYPE), '; ') WITHIN GROUP (ORDER BY ID) "product_listing"
FROM t1
GROUP BY ID

В данном случае, тип колонки type NVARCHAR2. В документации LISTAGG не специфицированы входные типы данных, только тип возврата:

The measure_expr is the measure column and can be any expression. [...]
If the measure column is of type RAW, then the return data type is RAW. Otherwise, the return data type is VARCHAR2.

Повидимому, при передаче как параметр не происходит неявного преобразования колонки type из типа NVARCHAR2 в VARCHAR2 (возможно баг). То есть, перекодировки символов не происходит, как в упрощённом примере:

select col,
    utl_raw.cast_to_varchar2 (utl_raw.cast_to_raw (col)) res
from (select n'Аренда' col from dual);

Результат полностью идентичен тому, как в вопросе, его привожу скрином, т.к. некоторые спез.символы не отображаются текстом на сайте:

введите сюда описание изображения


PS В последнем примере вопроса тоже не будет работать, если задать литерал правильно - n'Аренда' вместо 'Аренда'.

→ Ссылка