Функция 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 шт):
Решение: явно конвертировать функцией 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'Аренда' вместо 'Аренда'.
