ORA-22813: значение операнда превышает системный лимит
Не могу разобраться со смыслом ошибки в частном случае, дока сильно не спасла.
Выполняю запрос в SQL-окне PLSQLDeveloper'а:
SELECT *
FROM TABLE(pkg_products.get_products(i_var => 'some argument'));
Запрос возвращает три объекта типа object. У этого object'а есть поле field1, которое тоже является типом object (который содержит поля innerField1, ..., innerFieldN). При этом, в PLSQLDeveloper'е каждое поле внутреннего объекта также выводится в одну строку. Более того, одно из внутренних полей является коллекцией типа:
create or replace type t_StringList as table of varchar2(32767 char)
То есть результат запроса будет выглядеть как:
| field0 | field1.innerField1 | field1.innerField2 | field2 |
-------------------------------------------------------------------
| 3 | 'Hello,' | <Collection> | 12312 |
| 13 | 'World' | <Collection> | 3213 |
| 11 | '!' | <Collection> | 323 |
То есть, выводится три строки. Я хочу посмотреть на содержимое коллекции (в ячейке с коллекцией после выполнения запроса написано просто <Collection>). Кликаю на три точки рядом со значением ячейки:
После чего ожидаю увидеть в новом окне содержимое коллекции (список строк). Но вместо этого появляется указанная в заголовке ошибка:
При этом, в содержимом вроде как обычные короткие строки. Их видно, если выполнить PLSQL-блок:
declare
c t_StringList;
begin
c := pkg_products.get_products(i_var => 'some argument')(3).field1.innerField2;
for i in 1..c.count loop
dbms_output.put_line(c(i));
end loop;
end;
В консоли мы увидим вполне себе ожидаемые значения:
Ожидаемое_значение_1
Ожидаемое_значение_2
Ожидаемое_значение_3
Вопрос: какова природа ошибки и можно ли её как-то решить/обойти?
Ответы (1 шт):
Дело в том, что ограничение выбранo с символьной семантикой VARCHAR2 (32767 CHAR), то есть макс. кол-во символов в мультибайтной кодировке может быть FLOOR(32767/4) = 8191.
В PL/SQL документации об этом сказано следующее:
When declaring a CHAR or VARCHAR2 variable, to ensure that it can always hold n characters in any multibyte character set, declare its length in characters—that is, CHAR(n CHAR) or VARCHAR2(n CHAR), where n does not exceed FLOOR(32767/4) = 8191.
Этот лимит проверяется при конвертировании PL/SQL символьного типа в соответствующий ему SQL тип, при этом компилятор не учитавает, сколько символов действительно содержится в сущности этого типа.
Можно указать макс. длину в байтах, тогда будет работать (на db<>fiddle):
create or replace type StringList as table of varchar2 (32767 byte);
/
select column_value res from table (StringList ('abc','def'))
/
RES
--------
abc
def

