powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / FIBPlus: как получить возвращаемое хранимой процедурой значение?
25 сообщений из 48, страница 1 из 2
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582842
shalamyansky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Delphi XE3, FIBPlus 7.6, Firebird 3.0

Подскажите, пожалуйста, технику работу с компонентом TpFIBStoredProc. Требуется выполнить хранимую процедуру и получить возвращаемое ею значение. Делаю следующее:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
var
    StoredProc : TpFIBStoredProc;
begin
    ...
    StoredProc.GoToFirstRecordOnExecute := TRUE;
    StoredProc.ExecProc;
    if( not StoredProc.EOF )then begin
        Result := StoredProc.Fields[ 0 ].AsInteger;
    end;
end;



После исполнения процедуры запись существует и содержит корректное значение, и мы "стоим" на этой записи, что подтверждается корректным обращением к полю в отладчике. Однако свойство EOF почему-то установлено в TRUE, а RecordCount = 0. Во-первых, это странно, во-вторых, нужен способ проверить, не пуст ли выходной набор, и можно ли запрашивать значение поля. Нарываться на исключение очень не хочется. Или, возможно, существует другой способ получить возвращаемое значение(я) процедуры.

Или подскажите, где посмотреть примеры и документацию по FIBPlus. Сайт devrace.com мертвый.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582848
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Процедура селективная?

> Подскажите, пожалуйста, технику работу с компонентом TpFIBStoredProc.

ИМХО, лучшая техника работы с компонентом T***StoredProc -
использовать вместо него компонент T***Query.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582855
shalamyansky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гаджимурадов Рустамлучшая техника работы с компонентом T***StoredProc - использовать вместо него компонент T***Query.

TpFIBStoredProc - прямой наследник TpFIBQuery, добавляет к нему лишь пару невиртуальных методов, не имеющих отношения к рассматриваемой функциональности, так что в данном случае замена шила на мыло не поможет.

Не вполне понимаю, что такое селективная процедура. Вызванная через SELECT? Основанная на одном SELECT? Нет, процедура неселективная. Процедура проверяет некие условия, делает INSERT или UPDATE и возвращает идентификатор вставленной (обновленной) записи.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582860
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyanskyTpFIBStoredProc - прямой наследник TpFIBQuery

Уверен?.. Точно не путаешь её с TIBStoredProc и TIBQuery?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582867
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyansky> Не вполне понимаю, что такое селективная процедура.

Которая саспендит много строк.

> Процедура проверяет некие условия, делает INSERT или UPDATE
> и возвращает идентификатор вставленной (обновленной) записи.

Так может тогда правильнее не Fields дергать, а Params ?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582872
shalamyansky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovУверен?

Глазам своим верю. Тут есть, однако, особенность: TpFIBStoredProc и TpFIBQuery - вовсе не наследники TpFIBDataSet, как можно было бы ожидать. Из методов навигации у них есть только Next, что тоже неожиданно. И непонятное поведение EOF связано, скорее всего, именно с этим.
Гаджимурадов РустамТак может тогда правильнее не Fields дергать, а Params ?

Для получения результата?! Хм, попробую, но что-то мне удивителен этот путь.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582874
shalamyansky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробовал. Нет, число параметров осталось ровно тем же, только входные.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582879
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582880
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyansky,

и еще
http://www.ibase.ru/ibstp/
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582893
shalamyansky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я понял, что делать. Можно проверять StoredProc.BOF или StoredProc.Current.Count. Но можно и не проверять вовсе, потому что процедура ВСЕГДА возвращает значение, хоть какое-нибудь. Как и делают в статье, любезно указанной kdv. Моя привычка все проверять в данном случае оказалась не к месту.

Однако это все же не объясняет непонятное поведение EOF и RecordCount.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582911
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyanskyОднако это все же не объясняет непонятное поведение EOF и RecordCount.
потому что StoredProc это не датасет, а execute procedure - не рекордсет. После выполнения оно сразу считывает результат, в итоге EOF становится true.
с RecordCount примерно та же фигня - он увеличивается только при проходе по записям. А раз записей нет, EOF, значит Next не работает, ну и recordcount не инкрементируется.

См. FIBQuery.pas.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582926
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyansky,

Гаджимурадов Рустам...
ИМХО, лучшая техника работы с компонентом T***StoredProc -
использовать вместо него компонент T***Query.

+1

Пример использования:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create or alter procedure MY_PROC (
    A integer,
    B integer)
returns (
    RESULT integer)
as
begin
  result = a + b;
  suspend; /* Здесь - не обязательно */
end

=>
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
var
 Result : Integer;
 fQ : TpFIBQuery;
begin
  fQ := TpFIBQuery.Create(nil);
  try
  fQ.Database := pFIBDatabase1;
  fQ.Options := [qoStartTransaction];
  fQ.SQL.Text := 'Execute procedure My_Proc(:a, :b)';
  fQ.ParamByName('a').AsInteger := 2;
  fQ.ParamByName('b').AsInteger := 2;
  fQ.ExecQuery;
  Result :=  fQ.FieldByName('Result').AsInteger; // Результат
  finally
    fQ.Free
  end;
end;
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582929
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyansky...потому что процедура ВСЕГДА возвращает значение, хоть какое-нибудь...
Да хрен там.
shalamyansky...
Однако это все же не объясняет непонятное поведение EOF и RecordCount.

Ты не показал саму свою процедуру и способ обращения к ней.
Добавь в процедуру suspend - вот у тебя и EOF и RecodCount появятся. И результатов процедура сможет вернуть больше одного:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create or alter procedure MY_PROC (
    A integer,
    B integer)
returns (
    RESULT integer)
as
begin

  result = a; -- Первый результат
  suspend;

  result = b; -- Второй результат
  suspend;

end



Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
var
  Result: Integer;
  fRC: Integer;
  fQ: TpFIBQuery;
begin
  pFIBDatabase1.Open;
  fQ := TpFIBQuery.Create(nil);
  try
    fQ.Database := pFIBDatabase1;
    fQ.Options := [qoStartTransaction];
    fQ.SQL.Text := 'select result from My_Proc(:a, :b)'; // Обращаемся с процедурой как с табличкой
    fQ.ParamByName('a').AsInteger := 2;
    fQ.ParamByName('b').AsInteger := 3;

    fQ.ExecQuery;
    fRC := fQ.RecordCount; // Вот и RecordCount 
    while not fQ.Eof do begin // Вот и EOF
      Result := fQ.FieldByName('Result').AsInteger; // Перебор всех результатов
      fQ.Next;
    end;
  finally
    fQ.Free
  end;
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582936
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДТы не показал саму свою процедуру и способ обращения к ней.
Добавь в процедуру suspend - вот у тебя и EOF и RecodCount появятся.

При execute procedure - не появятся.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582937
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovчччДТы не показал саму свою процедуру и способ обращения к ней.
Добавь в процедуру suspend - вот у тебя и EOF и RecodCount появятся.

При execute procedure - не появятся.

Ну я там ниже другой код привел, не EP...
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39582947
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyanskyТут есть, однако, особенность: TpFIBStoredProc и TpFIBQuery - вовсе не наследники TpFIBDataSet, как можно было бы ожидать. Из методов навигации у них есть только Next, что тоже неожиданно. И непонятное поведение EOF связано, скорее всего, именно с этим.


Вот как раз логично было бы ожидать что TpFIBDataSet является наследником, или использует у себя TpFIBQuery а никак не наоборот.

Вообще, обычно сервер выдает не какой-то там мифический датасет, а тупо массив записей.
TpFIBQuery а так же TIBSQL имеют буфер только на одну запись. Выполняется запрос и читается 1 запись.
По Next читается следующая запись. И так до конца. Конец определяется по EOF = True.
Возврат обратно невозможен поскольку некуда возвращаться.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583367
shalamyansky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем спасибо! В тему вошел, как действовать, понял.

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

1. Хранимые процедуры самим своим синтаксисом и механизмом возврата значений задуманы как аналогия DataSet. Когда мы их вызываем через SELECT ли, через EXECUTE ли, получаем набор записей, одну, несколько, или ни одной, точно так же, как при работе с "обычным" DataSet и техника работы с ними интуитивно ожидается такой же. А она другая. Это неудобно. Возможно, мне для вызова процедуры стоило использовать TpFIBDataSet.

2. Вызывая процедуру на клиенте (да и на сервере тоже), мы не можем быть абсолютно уверены, что она вернет не пустой набор. Поэтому код, прежде чем забрать результат из буфера, должен удостовериться, что буфер не пуст. На мой взгляд, код
Код: pascal
1.
2.
fQ.ExecQuery;
Result :=  fQ.FieldByName('Result').AsInteger; // Результат


небезопасен, а должен выглядеть, как
Код: pascal
1.
2.
3.
4.
5.
6.
fQ.ExecQuery;
if( fQ.Current.Count > 0 )then begin
    Result := fQ.FieldByName( 'Result' ).AsInteger; // Результат
end else begin
    //что-то пошло не так
end;


Спасает свойство Current.Count. В "традиционной" технике для проверки использовалось свойство EOF.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583391
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyansky1. Хранимые процедуры самим своим синтаксисом и механизмом возврата значений задуманы как аналогия DataSet. Когда мы их вызываем через SELECT ли, через EXECUTE ли, получаем набор записей, одну
нэт.
Хранимые процедуры не имеют ничего общего с датасетом. В InterBase и Firebird хранимые процедуры МОГУТ быть селективными, при использовании слова SUSPEND, и ни в каком другом случае датасетами они не являются, как и операторы INSERT, UPDATE, DELETE.
shalamyanskyтехника работы с ними интуитивно ожидается такой же.
впервые универсальный датасет и универсальный TStoredProc появились в универсальном же BDE. Для массы серверов процедуры не предполагают никакого возврата "наборов записей", поэтому TStoredProc и не являлся исходно датасетом.
Соответственно, "интуитивно" никто от StoredProc "датасетности" и не ожидал.
shalamyansky Вызывая процедуру на клиенте (да и на сервере тоже), мы не можем быть абсолютно уверены, что она вернет не пустой набор
это тоже ересь. Потому что селективная процедура при вызове через select ведет себя абсолютно как и любой другой select. А при вызове через execute procedure - НЕ как рекордсет.

В общем, оба ваши домысла основаны на неверных исходных предпосылках.

Я замечу, что абсолютно такая же "интуиция" у людей, которые, например, запросу INSERT делают DataSet.Open.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583398
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyanskyХранимые процедуры самим своим синтаксисом и механизмом возврата значений задуманы как аналогия DataSet
Это не так. Процедура - изначально только для того нужна, чтобы что-то сделать на сервере и вернуть результат (в OUT-параметре).
Просто для удобства добавили возможность работы с ней как с DataSet.
shalamyanskyКогда мы их вызываем через SELECT ли, через EXECUTE ли, получаем набор записей
Это не так. Через EXECUTE ты не получишь набор записей, даже если процедура и могла бы их вернуть, вызови ты её через SELECT. Ты получишь только результаты в OUT-параметрах (соответствующие значениям полей в 1-й записи или их DEFAULT-значения, если записей нет, или исключение, если OUT-параметр объявлен как NOT NULL и он не был инициализирован).
А НЕселективную (в теле которой нет SUSPEND) процедуру так и вообще нельзя вызвать через SELECT, и это правильно. Лучше б и селективные запретили вызывать через EXECUTE, как по мне.
shalamyanskyнебезопасен, а должен выглядеть, как
Код: pascal
1.
2.
3.
4.
5.
6.
fQ.ExecQuery;
if( fQ.Current.Count > 0 )then begin
    Result := fQ.FieldByName( 'Result' ).AsInteger; // Результат
end else begin
    //что-то пошло не так
end;


Не знаю, как в FIBPlus, в IBX я пишу так и всё работает всегда:
Код: pascal
1.
2.
sp.ExecProc;
Result := sp.ParamByName( 'Result' ).AsInteger; // Результат


И "что-то не так" пойти не может, либо будет исключение.
Это для НЕселективных процедур.
А для селективных - понятное дело, есть First,Eof,Next.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583402
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockА НЕселективную (в теле которой нет SUSPEND) процедуру так и вообще нельзя вызвать через
SELECT

Можно. Только она вернёт пустой result set, поскольку технически отсутствующий suspend
ничем не отличается от наличествующего, который ни разу не был вызван.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583404
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovYuRockА НЕселективную (в теле которой нет SUSPEND) процедуру так и вообще нельзя вызвать через
SELECT

Можно. Только она вернёт пустой result set, поскольку технически отсутствующий suspend
ничем не отличается от наличествующего, который ни разу не был вызван.
У меня всегда такое она возвращает:
non-SQL security class defined.
Dynamic SQL Error.
SQL error code = -84.
procedure PROCEDURENAME does not return any values.
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583406
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
shalamyansky> Всем спасибо! В тему вошел, как действовать, понял.

Низачот. Ибо дальше ты генерируешь несоответствующие реальности представления, рассуждения и выводы.
~~~~~~~~~~~~~~~~~~~~~~~~

Процедуры бывают разных типов.
1. Исходя из задачи, создаешь процедуру нужного тебе типа.
2. Обращаешься к процедуре так, того требует задача.
0. Ты не рассказал о своей задаче, не показал процедуры, но мучаешь абстрактную сову реальным глобусом.
-1. Смысла фантазировать нет, когда доступна документация (на русском языке).
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583407
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ой, не такую. Такую:
Invalid token.
invalid request BLR at offset 23.
Procedure PROCEDURENAME is not selectable (it does not contain a SUSPEND statement).
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583408
ччч
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock...Не знаю, как в FIBPlus, в IBX я пишу так и всё работает всегда:...
Теперь скажи - нах.. это тайное знание автору вопроса?
...
Рейтинг: 0 / 0
FIBPlus: как получить возвращаемое хранимой процедурой значение?
    #39583418
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
12.01.2018 16:55, YuRock пишет:
> Procedure PROCEDURENAME is not selectable (it does not contain a SUSPEND statement).

это не так давно ввели - селективные/неселективные.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
25 сообщений из 48, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / FIBPlus: как получить возвращаемое хранимой процедурой значение?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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