CftClub.ru
Клуб специалистов ЦФТ-Банк

Размерность строковой переменной

 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle
Предыдущая тема :: Следующая тема  
Автор Сообщение
danzki
Участник - экстремал


Вступление в Клуб: 30.09.2010
СообщениеСр Авг 20, 2014 10:08   Размерность строковой переменной Ответить с цитатой
Полезность: Нет оценки
Коллеги,
обнаружил проблему с функциями, возвращающими строку.
Покажу на примере.

Глобальное описание
Код:
function Get_client_acc(cl ref [CLIENT]) return varchar2(32000);


Локальное описание (только заголовок)
Код:
function Get_client_acc(cl ref [CLIENT]) return varchar2(32000) is
acc_client varchar2(32000)  := NULL;
begin
...
return acc_client;
end;


Если посмотреть PL/SQL пакет (по F12), то обнаружим неприятную штуку

Спецификация
Код:
function GET_CLIENT_ACC(CL IN number) return varchar2;


Боди пакета
Код:
function GET_CLIENT_ACC(CL IN number) return varchar2 is
   ACC_CLIENT   varchar2(32000) := null;
begin
...
RETURN ACC_CLIENT;
end;


Т.е. для возвращаемого значения размерность пропадает.

При этом если пытаемся вернуть больше 4000 все валится - character string buffer too small

Кто-нибудь сталкивался?
vtar
Эксперт


Вступление в Клуб: 20.03.2009
СообщениеСр Авг 20, 2014 10:21    Ответить с цитатой
Полезность: Нет оценки
Это вроде как ограничение oracle
http://cftclub.ru/viewtopic.php?t=3264&highlight=4000
для больше, пользуйте CLOB или заполняйте table()
client(1).acc(1)
client(1).acc(2)
Alex294
Участник со стажем


Вступление в Клуб: 02.06.2013
СообщениеСр Авг 20, 2014 11:16    Ответить с цитатой
Полезность: 1
На самом деле это ограничение Oracle SQL, для PL/SQL такого ограничения нет.
Функция:
Код:
function Gen_memo return varchar2(32767)
is
begin
   return RPAD('A', 5000, 'a');
end;

хотя преобразуется в:
Код:
   function GEN_MEMO return varchar2 is
   begin
--# 9,2
      return RPAD('A',5000,'a');
   end;

отрабатывает на ура:
Код:
If P_MESSAGE = 'DEFAULT' then
   P_MSG := Gen_memo();
end if;

P-MSG имеет тип Мемо_32767.
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеСр Авг 20, 2014 13:23   Re: Размерность строковой переменной Ответить с цитатой
Полезность: 2
danzki пишет:
Коллеги,
обнаружил проблему с функциями, возвращающими строку.
Покажу на примере.

Глобальное описание
Код:
function Get_client_acc(cl ref [CLIENT]) return varchar2(32000);


Локальное описание (только заголовок)
Код:
function Get_client_acc(cl ref [CLIENT]) return varchar2(32000) is
acc_client varchar2(32000)  := NULL;
begin
...
return acc_client;
end;


Если посмотреть PL/SQL пакет (по F12), то обнаружим неприятную штуку

Спецификация
Код:
function GET_CLIENT_ACC(CL IN number) return varchar2;


Боди пакета
Код:
function GET_CLIENT_ACC(CL IN number) return varchar2 is
   ACC_CLIENT   varchar2(32000) := null;
begin
...
RETURN ACC_CLIENT;
end;


Т.е. для возвращаемого значения размерность пропадает.

При этом если пытаемся вернуть больше 4000 все валится - character string buffer too small

Кто-нибудь сталкивался?


при объявлении возвращаемого типа из функции в PL/SQL и PL/PLUS можно объявить только тип данных, но никак не размерность.
Код:
function test return varchar2(100) is
- в PL/SQL просто не скомпилируется. А в PL/PLUS будет заменена на валидный тип без всяких размерностей. Аналогично для параметров, кстати.

Размерность определяется переменной или функцией или константой, которая реально возвращается.

Например, в PL/PLUS
Код:
function test return varchar2(100) is
vRet varchar2(1000); -- а вот и реальный размер !!!
begin
   vRet := lpad(' ',1000,' ');
  return vRet;
end;
прекрасно НЕ ломается. Но ломает шаблон разработчику, поэтому, ПОЖАЛУЙСТА, не используйте размерности ни в параметрах функций, ни в результирующих значениях...

А у вас дело в том, что вы проверяете функцию с помощью SQL-запроса.
Код:
select Z$имя пакета.GET_CLIENT_ACC(z.id) from z#client z

В SQL максимальный размер строки - 4000, а в PL/SQL - 32767 символов. Соответственно, функция вполне может вернуть строчку больше 4к:
Код:
declare
v varchar2(32767);
begin
  v := rtl.open;
  select id into v from z#client where rownum < 2;
  v := Z$имя пакета.GET_CLIENT_ACC(v);
end;

вот только использовать эту функцию в запросах и представлениях уже не получится.
danzki
Участник - экстремал


Вступление в Клуб: 30.09.2010
СообщениеСр Авг 20, 2014 14:22    Ответить с цитатой
Полезность: Нет оценки
Random, Alex294, спасибо за исчерпывающий ответ. Все так и есть
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru