powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / [ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
11 сообщений из 11, страница 1 из 1
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32709848
Bonart
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Создана ХП без раздела RESULT. ХП возвращает в зависимости от параметров наборы с различным количеством полей.
Первый вызов происходит нормально, второй и последующие (с другими значениями параметров) ругается на отсутствие полей из предыдущего вызова .
Т.е. пишет "Column 'CCC' not found", где 'CCC' - поле из предыдущего вызова.

В ХП: объявляется временная локальная таблица, динамическим курсором в нее запихиваются данные, в конце делается SELECT * FROM <временная таблица>.
Если это имеет значение, то в теле ХП используется Execute Immediate, разумеется.

Проблема возникает как в Sybase Central, так и в проге на Дельфи, которая работает через ODBC.

Как лечится?

P.S. Как показатель правильности работы процедуры работает следующий код (в I-SQL Sybase Central):

Код: plaintext
1.
2.
DROP PROCEDURE <ХП>;
CREATE  PROCEDURE <ХП> (...);
CALL <ХП>(...);

Отрабатывается нормально с разными значениями параметров.
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32709946
Фотография Badger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может я не все понимаю, но если входящие параметры
процедуры запихнуть в таблицу, для этого пользователя,
а потом процедуру вызвать без параметров, то правильный
результат получится? Или так нельзя?
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32709948
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробуйте в ХП вызывать EXECUTE IMMEDIATE с параметром WITH RESULT SET ON, может быть поможет.
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32711153
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BonartСоздана ХП без раздела RESULT. ХП возвращает в зависимости от параметров наборы с различным количеством полей.
Первый вызов происходит нормально, второй и последующие (с другими значениями параметров) ругается на отсутствие полей из предыдущего вызова .
Использую такую схему очень часто (еще со времен ASA7) и никаких проблем не возникало. Где-то у вас что-то не то....

Вот пример одной из моих процедур:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
CREATE PROCEDURE DBA.Report_154(in pRepPart numeric( 2 ))
BEGIN
	CASE pRepPart
	WHEN  1  THEN
		create table #r1(CC money, CK money, LN money, M money, Total_Revenue money);
		insert into #r1 ..... ;
		select * from #r1;

	WHEN  2  THEN
		create table #r2(PY money, RF money, RC money, SP money, DA money, XC money, Total_Deductions money);
		insert into #r2 ..... ;
		select * from #r2;


	WHEN  3  THEN
		select isnull(sum(SummaryPayment), 0 ) as Additional_Revenue from SomeTable;

[.......]
	ELSE
		 -- количество секций в отчете 
		select  7 ;
	END CASE; 
	
END;


Код: plaintext
1.
2.
В ХП: объявляется временная локальная таблица, динамическим курсором в нее запихиваются данные, в конце делается SELECT * FROM <временная таблица>.
Если это имеет значение, то в теле ХП используется Execute Immediate, разумеется.
Это все не важно, формировать резалт-сэт можно как угодно. Впрочем, я не уверен насчет execute immediate. Оно может и хулиганить в этой ситуации, я сам эту конструкцию не использую почти никогда.

Очень сильно подозреваю, что ошибка возникает когда вызов multi-resultset процедуры делается из другой процедуры? Там может начаться конфликт из-за того, что в первый запуск процедуры делается ее компиляция и откомпилировання процедура кладется в кеш, на повторном запуске соотвественно возникает проблема толи взять процедуру из кеша, толи откомпилировать ее заново...

В качестве лечения предлагаю делать вызовы процедуры не через простой call а через execute immediate 'call my_super_sp(1)';
Может помочь разнести повторные вызовы процедуры по разным транзакциям, или даже по разным коннектам к базе.

У меня эти процедуры вызываются из PowerBuilder через ODBC со всеми стандартными настройками. Просто в композитном DW лежат несколько дочерних DW с простыми вызовами процедуры с разными параметрами.
В Delphi я их вызываю через SaVCL, тоже проблем не возникало. Оба режима работы с транзакциями без малейших проблем.
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32712618
Bonart_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ничего не помогло.
Такое ощущение, что список полей результата где-то хитро кэшируется, потом вызывается из кэша, несмотря на то, что это нафиг не нужно.
В документации на это косвенно указывается фразой:
"Если не используется возможность возвращения различных результирующих
наборов, по соображениям производительности следует включить раздел
RESULT."
Еще дока упоминает оператор DESCRIBE, но я что-то не понял зачем он нужен, да и ругается на него тот же Sybase Central - синтаксическая ошибка.

Если кто объяснит на пальцах - буду благодарен.


White Owl BonartСоздана ХП без раздела RESULT. ХП возвращает в зависимости от параметров наборы с различным количеством полей.
Первый вызов происходит нормально, второй и последующие (с другими значениями параметров) ругается на отсутствие полей из предыдущего вызова .
Использую такую схему очень часто (еще со времен ASA7) и никаких проблем не возникало. Где-то у вас что-то не то....

Вот и я хотел бы понять где у меня что-то не то.

Ок, приведу свою процедуру:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
 // выдает отчет о динамике дохода: в зависимости от параметра GPeriod 
 // либо по неделям, либо по месяцам, по кварталам или по годам. 
Create PROCEDURE "RepDyn"
(
 in date_begin date,  // начало отчетного периода 
 in date_end date,  // конец отчетного периода 
 in GPeriod varchar( 10 )  // 'квант' отчета 
)
BEGIN
  declare v_ColCount integer;  // кол-во 'квантов' в отчете 
  declare i integer;  // циклическая переменная 
  declare iDate date;   // циклическая переменная для генерации имени столбца-'кванта' 
  declare v_ColName varchar( 30 );  // имя столбца-'кванта' 
  declare query long varchar;  // SQL-предложение для создания временной результирующей таблицы 
  declare v_ID integer;  // текущий ID временной таблицы 

 // вычисление количества 'квантов' (недель или месяцев или кварталов ...) 
 // Execute используется, т.к. GPeriod - строковый параметр. 
  Execute( 
    ' set v_ColCount = ( select 1 + 
                         ( case GPeriod 
                            when ''week'' 
                             then  DateDiff( week, date_begin - 1, date_end - 1 ) 
                             else  DateDiff( '+ GPeriod +', date_begin, date_end ) 
                           end 
                          )
                        ); 
                       ' );
 
  set i =  1 ;
  set iDate = date_begin;
  set query = '  Declare local temporary TABLE tmp_tbl (
                   ID unsigned int primary key, 
                    [Тип] varchar(100) ';

 // генерация скрипта на создание временной таблицы 
  while i <= v_ColCount loop
    case GPeriod
      when 'week'    then
                         set v_ColName = DateFormat( iDate, 'dd.mm.yy')|| '-';
                         set iDate = Lesser( date_end, DateAdd(day, (if DoW(iDate)= 1  then   0  else  8 -DoW(iDate) endif), iDate) );
                         set v_ColName = v_ColName || DateFormat( iDate, 'dd.mm.yy');
                         set iDate = iDate +  1 

      when 'month'   then
                         set v_ColName = MonthNameRus(iDate) ||' '|| year(iDate);
                         set iDate = dateadd( month,  1 , iDate )

      when 'quarter' then 
                         set v_ColName = quarter(iDate) ||' кв. '|| year(iDate);
                         set iDate = dateadd( quarter,  1 , iDate )

      when 'year'    then
                         set v_ColName = year(iDate);
                         set iDate = ymd(  1  + year(iDate),  1 ,  1  )
    end case;

    set query = query + ', ['+ v_ColName +'] money ';
    set i = i +  1 ;
  end loop;

  Execute( query +');' );

  set v_ID = null;
  For c1 as curs dynamic scroll cursor for
    select
        ID as ID_T,
        Name as Name_T,

       (case GPeriod
          when 'week'    then  1 + datediff(   week, date_begin- 1 , edate- 1 )
          when 'month'   then  1 + datediff(  month, date_begin,   edate)
          when 'quarter' then  1 + datediff(quarter, date_begin,   edate)
          when 'year'    then  1 + datediff(   year, date_begin,   edate)
        end          )  as GroupPeriod,   // номер 'кванта' 

 // edate - поле: дата прихода денег 


       (case GPeriod
          when 'week'    then 
                        DateFormat( Greater( date_begin, DateAdd(day, (if DoW(edate)= 1  then - 6  else  2 -DoW(edate) endif), edate) ), 'dd.mm.yy')
                        || '-' ||
                        DateFormat( Lesser (   date_end, DateAdd(day, (if DoW(edate)= 1  then   0  else  8 -DoW(edate) endif), edate) ), 'dd.mm.yy')
          when 'month'   then MonthNameRus(edate) ||' '|| year(edate)
          when 'quarter' then quarter(edate) ||' кв. '|| year(edate)
          when 'year'    then cast( year(edate) as varchar( 30 ) )
        end           )  as NameGroupPeriod,  // имя 'кванта' и соответствующего столбца в tmp_tbl 

       sum( Prib ) as Prib_T  // Prib - поле: сумма пришедших денег 

      from ...

      group by  ID_T,
	Name_T,
                GroupPeriod,
                NameGroupPeriod
      order by  1 , 2 , 3 
  Do
    if (v_ID <> ID_T) or (v_ID is null)  then
      set v_ID = ID_T;
      insert into tmp_tbl (ID, [Тип]) values (v_ID, Name_T);
    end if;

    Execute( 'update tmp_tbl set ['+ NameGroupPeriod +'] = Prib_Type where ID = v_ID;' );

  End For;
 
  select * from tmp_tbl;
END;

В итоге, в зависимости от дат и кванта получаются таблицы вида:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
---
date_begin = 01.01.04
date_end =   01.02.04
GPeriod = 'week'
-
ID	Тип	01.01.04-04.01.04	05.01.04-11.01.04	12.01.04-18.01.04	19.01.04-25.01.04	26.01.04-01.02.04
-----------------------------------------------------------------------------------------------------------
1	A	3630.00		9720.00		12520.00		3080.00		4840.00
2	B	19570.00		51290.00		51510.00		55540.00		59540.00
3	C	127040.00		339800.00		363300.00		287350.00		331485.00
===
date_begin = 01.01.04
date_end =   01.04.04
GPeriod = 'month'
-
ID	Тип	Январь 2004	Февраль 2004	Март 2004		Апрель 2004
-----------------------------------------------------------------------------------------
1	A	33790.00		105500.00		292695.00		-5010.00
2	B	228360.00		274630.00		296120.00		6410.00
3	C	1369585.00	1366125.00	1675495.00	10575.00
5	E							20.00
===


В ХП: объявляется временная локальная таблица, динамическим курсором в нее запихиваются данные, в конце делается SELECT * FROM <временная таблица>.
Если это имеет значение, то в теле ХП используется Execute Immediate, разумеется.

Это все не важно, формировать резалт-сэт можно как угодно. Впрочем, я не уверен насчет execute immediate. Оно может и хулиганить в этой ситуации, я сам эту конструкцию не использую почти никогда.

Отладчик в Sybase Central не ругается, ни на одну строчку. Ошибка выдается уже после End; процедуры.

Есть еще один момент: "нормальные" процедуры (у которых есть RESULT) я вызываю не CALL'ом, а
Код: plaintext
SELECT * FROM <ХП>(...);
И с ними все ок. А с этой выдается: '<ХП> returned a result set with a different schema than expected'. Что бы это значило?

Очень сильно подозреваю, что ошибка возникает когда вызов multi-resultset процедуры делается из другой процедуры?
Нет. RepDyn вызывается в "чистом виде", т.е. либо call RepDyn в Sybase Central или в компоненте TQuery , либо методом Execute компонента TStoredProc .

Там может начаться конфликт из-за того, что в первый запуск процедуры делается ее компиляция и откомпилировання процедура кладется в кеш, на повторном запуске соотвественно возникает проблема толи взять процедуру из кеша, толи откомпилировать ее заново...
У меня была та же мысль, только процедура-то запускается с нуля.


В качестве лечения предлагаю делать вызовы процедуры не через простой call а через execute immediate 'call my_super_sp(1)';
Может помочь разнести повторные вызовы процедуры по разным транзакциям, или даже по разным коннектам к базе.
Не работает. Пишет "Result set not permitted in RepDyn".


У меня эти процедуры вызываются из PowerBuilder через ODBC со всеми стандартными настройками. Просто в композитном DW лежат несколько дочерних DW с простыми вызовами процедуры с разными параметрами.
В Delphi я их вызываю через SaVCL, тоже проблем не возникало. Оба режима работы с транзакциями без малейших проблем.
Что такое DW?
Что такое SaVCL? Если библиотека, то где взять можно?
PowerBuilder'ом не пользуюсь...

Без перечисленного можно обойтись?

Чайник я в общем...

P.S. если всю эту ботву генерить в дельфийском коде (компонент SQLScript), то все работает, просто хочется побольше в сервер упихать, поменьше дельфи кодом засорять.
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32712921
VadimS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня была похожая ситуация. Скорее всего при первом вызове процедура компилируется и запоминает структуру временной таблицы. При повторном вызове - выполняется уже откомпилированный код процедуры со старой структурой. Я перед скриптом создания временной таблицы выполняю
Код: plaintext
1.
2.
3.
4.
  if exists(select* from SysTable where Table_type = 'BASE' and table_name = 'tmptable') then
      drop table tmptable;
      commit work
    end if;
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32713323
Bonart_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 VadimS

Не помогло.
Я думаю, если бы было так как ты сказал - была бы ругань уже в районе
Код: plaintext
Declare local temporary table tmp_tbl
а также там, где я делаю INSERT и UPDATE в tmp_tbl.
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32713616
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bonart_Такое ощущение, что список полей результата где-то хитро кэшируется, потом вызывается из кэша, несмотря на то, что это нафиг не нужно.

Да, кешируется. Я же говорю - процедура при первом старте компилируется и для нее формируется вспомогательный RESULT(f1, f2,etc);

Bonart_Еще дока упоминает оператор DESCRIBE, но я что-то не понял зачем он нужен, да и ругается на него тот же Sybase Central - синтаксическая ошибка.
Это оператор из Embedded SQL. Можешь пока не обращать на него внимания.

Код: plaintext
1.
2.
3.
  set query = '  Declare local temporary TABLE tmp_tbl (
                   ID unsigned int primary key, 
                    [Тип] varchar(100) ';
я сильно возражаю против вот этого. Лучше объявляй десяток разных временных таблиц с жестко заданной структурой в таблицах.
Функция Execute() очень сложна для оптимизатора и ее лучше использовать как можно реже.

Bonart_
Отладчик в Sybase Central не ругается, ни на одну строчку. Ошибка выдается уже после End; процедуры.
Ошибка выдается на "select *" потому что оно было оптимизировано и положено в кеш. Да, в теории оно все должно работать так как написано. Но оптимизатор не правильно кеширует результаты execute() c последующим select *.
Сделай несколько временных таблиц с жестко заданной структурой, и делай выборку из них. Проблема исчезнет 100%.


Bonart_У меня была та же мысль, только процедура-то запускается с нуля.
Ха! "С нуля" процедура запускается только один раз - после старта сервера. После этого кеш всегда вмешивается.


Bonart_Что такое DW?
DataWindow - это... помесь TQuery, TDataGrid и все отчетные библиотеки вместе взятые :) Короче это то, через что PB делает запросы к базе и показывает результаты запроса.

Bonart_Что такое SaVCL? Если библиотека, то где взять можно?
Библиотека для Borland`овских языковых систем. savcl.narod.ru
Читайте местный FAQ там все написано.

Bonart_Без перечисленного можно обойтись?
Конечно можно.
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32713739
Bonart_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl Bonart_Такое ощущение, что список полей результата где-то хитро кэшируется, потом вызывается из кэша, несмотря на то, что это нафиг не нужно.

Да, кешируется. Я же говорю - процедура при первом старте компилируется и для нее формируется вспомогательный RESULT(f1, f2,etc);

Хм. Тогда глупый вопрос: в чем тогда профит возможности возвращать different result sets?...



Код: plaintext
1.
2.
3.
  set query = '  Declare local temporary TABLE tmp_tbl (
                   ID unsigned int primary key, 
                    [Тип] varchar(100) ';
я сильно возражаю против вот этого. Лучше объявляй десяток разных временных таблиц с жестко заданной структурой в таблицах.
Функция Execute() очень сложна для оптимизатора и ее лучше использовать как можно реже.

Bonart_
Отладчик в Sybase Central не ругается, ни на одну строчку. Ошибка выдается уже после End; процедуры.
Ошибка выдается на "select *" потому что оно было оптимизировано и положено в кеш. Да, в теории оно все должно работать так как написано. Но оптимизатор не правильно кеширует результаты execute() c последующим select *.
Сделай несколько временных таблиц с жестко заданной структурой, и делай выборку из них. Проблема исчезнет 100%.

Да я бы с удовольствием, однако исходя из поставленной задачи: количество столбцов заранее неизвестно в принципе, равно как и их названия. В общем и целом они могут быть любыми (и имена столбцов и их количество).



Bonart_У меня была та же мысль, только процедура-то запускается с нуля.
Ха! "С нуля" процедура запускается только один раз - после старта сервера. После этого кеш всегда вмешивается.

Ну я имел ввиду, что не из другой процедуры.

А этим кэшем как-нибудь можно управлять интерактивно?



Bonart_Что такое DW?
DataWindow - это... помесь TQuery, TDataGrid и все отчетные библиотеки вместе взятые :) Короче это то, через что PB делает запросы к базе и показывает результаты запроса.

Bonart_Что такое SaVCL? Если библиотека, то где взять можно?
Библиотека для Borland`овских языковых систем. savcl.narod.ru
Читайте местный FAQ там все написано.

Эээ... ткни, плиз, носом, где в FAQ'е об этом.
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32713770
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Bonart_Хм. Тогда глупый вопрос: в чем тогда профит возможности возвращать different result sets?...
Ну как это в чем? В том, что можно держать всю логику в одной процедуре. У меня почти все многосекционные отчеты так сделаны.

Лучше объявляй десяток разных временных таблиц с жестко заданной структурой в таблицах.
Да я бы с удовольствием, однако исходя из поставленной задачи: количество столбцов заранее неизвестно в принципе, равно как и их названия. В общем и целом они могут быть любыми (и имена столбцов и их количество).
Ну вообще-то, это не совсем задача для БД. Это скорее клиенту пристало кросс-табы рисовать.... А попробуй имена темп-таблиц тоже менять? Раз уж ты так сильно хочешь строить временную таблицу в рантайме, то сделай ей и имя еще переменным. Может заработать.
Хотя я бы, все же, переложил бы задачу построенния шахматки на клиента. Сервер может выдавать уже готовые цифры, а клиент только чтоб форматировал результат.



А этим кэшем как-нибудь можно управлять интерактивно?

Насколько я знаю - нет.

Эээ... ткни, плиз, носом, где в FAQ'е об этом.
http://www.sql.ru/faq/faq_topic.aspx?fid=184
...
Рейтинг: 0 / 0
[ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
    #32720343
Bonart
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl Bonart_Хм. Тогда глупый вопрос: в чем тогда профит возможности возвращать different result sets?...
Ну как это в чем? В том, что можно держать всю логику в одной процедуре. У меня почти все многосекционные отчеты так сделаны.

Да, но если это не работает?
Впрочем, это уже лирика, фиг с ней.


White Owl Bonart White OwlЛучше объявляй десяток разных временных таблиц с жестко заданной структурой в таблицах.
Да я бы с удовольствием, однако исходя из поставленной задачи: количество столбцов заранее неизвестно в принципе, равно как и их названия. В общем и целом они могут быть любыми (и имена столбцов и их количество).
Ну вообще-то, это не совсем задача для БД. Это скорее клиенту пристало кросс-табы рисовать.... А попробуй имена темп-таблиц тоже менять? Раз уж ты так сильно хочешь строить временную таблицу в рантайме, то сделай ей и имя еще переменным. Может заработать.

Т.е. снова execute использовать?
Что-то не сработало - выдает непонятное "Result set not permitted in `<batch statement>`".


Хотя я бы, все же, переложил бы задачу построенния шахматки на клиента. Сервер может выдавать уже готовые цифры, а клиент только чтоб форматировал результат.
На клиент неинтересно, особенно учитывая, что гриды автоматически поля генерят.
Ну а так проще, имхо, все в код упихать, как сейчас.



Эээ... ткни, плиз, носом, где в FAQ'е об этом.
http://www.sql.ru/faq/faq_topic.aspx?fid=184
Сэнькс, проглядел.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Sybase ASA, ASE, IQ [игнор отключен] [закрыт для гостей] / [ASA 9.0.0.1321] Проблема с возвратом набора из ХП без указания его полей
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]