Здравствуйте.
Я выбираю компоненты для Postgres+Lazarus, заказчики хотят переехать с FireBird на Postgres, на данный момент для работы с FireBird использую собственный форк IBX, переделанный по типу FIBPlus. Ищу компоненты с подобным функционалом для Postgres чтобы на клиенте было минимум изменений. Есть вопросы по pgDac.
У меня сейчас механизм на FireBird работает следующим образом:
1. Генерацию первичных ключей я задаю на стороне сервера. В Insert запросах использую выражение Returning для возврата первичного ключа, таким образом ключ генерится на сервере и автоматически подставляется в набор данных в момент выполнения метода Post, никаких генераторов на клиенте указывать не нужно. Получив первичный ключ автоматически срабатывает refresh текущей записи по первичному ключу.
Можно ли с pgDac работать так-же, используя генерацию первичного ключа на стороне сервера и через выражение returning в insert запросе подставлять его в набор данных?
2 Все то-же самое, но в Insert запросе используется хранимая процедура, которая после вставки возвращает первичный ключ и он подставляется в набор данных.
3. Я пробовал использовать SQLdb из состава лазарус, но подтверждение транзакции после вставки, редактирования, удаления данных закрывает все наборы данных, SELECT по новой открывать надо.
Как с этим обстоят дела в pgDac?
pgDac есть вопросы
Re: pgDac есть вопросы
1. Об использовании в PgDAC ключевого слова RETURNING для получения значения со стороны PostgreSQL вы можете найти в нашей онлайн-документации: http://www.devart.com/pgdac/docs/index. ... ration.htm
Также PgDAC умеет автоматически получать значение ключевого поля, которое генерируется на сервере. Например:
2. Пожалуйста, покажите нам INSERT SQL запрос, в котором вы используете хранимую процедуру, а также скприпт для создания этой хранимой процедуры.
3. PgDAC при вызове метода TPgConnection.Commit не закрывает датасеты, которые используют этот экземпляр соединения.
Также PgDAC умеет автоматически получать значение ключевого поля, которое генерируется на сервере. Например:
Код: Выделить всё
PgQuery1.SQL.Text := 'select * from emp;';
PgQuery1.DMLRefresh := True;
PgQuery1.Active := True;
PgQuery1.Insert;
PgQuery1.FieldByName('ename').AsString := 'Testing.';
PgQuery1.Post;
ShowMessage('New empno = ' + PgQuery1.FieldByName('empno').AsString);
3. PgDAC при вызове метода TPgConnection.Commit не закрывает датасеты, которые используют этот экземпляр соединения.
-
- Сообщения: 2
- Зарегистрирован: Вт 16 янв 2018 06:20
Re: pgDac есть вопросы
Пример функции, делает вставку в таблицу baseuser, возвращает первичный ключ baseuser_id через выходной параметр out_baseuser_id. Я бы хотел вызов такой функции вставить в InsertSQL набора данных. Как-то можно приспособить, чтобы выходной параметр out_baseuser_id сам подставлялся в набор данных после выполнения вставки записи?
Код: Выделить всё
CREATE OR REPLACE FUNCTION public.f_baseuser_ins (
iarh boolean,
iregdata date,
isfam varchar,
isimja varchar,
isotch varchar,
ibrig integer,
out out_baseuser_id bigint
)
RETURNS bigint AS
$body$
DECLARE
iuserfio VARCHAR(100);
BEGIN
IF iarh IS NULL THEN
iarh := FALSE;
END IF;
iuserfio := isfam || ' ' || isimja;
IF isotch <> '' THEN
iuserfio := iuserfio || ' ' || isotch;
END IF;
INSERT INTO baseuser
(
userfio,
arh,
regdata,
sfam,
simja,
sotch,
brig
)
VALUES
(iuserfio,
iarh,
iregdata,
isfam,
isimja,
isotch,
ibrig
)RETURNING baseuser_id INTO out_baseuser_id;
RETURN;
END;
Re: pgDac есть вопросы
Чтобы получить значение OUT параметра после вызова хранимой процедуры, используйте компонент TPgStoredProc. Например:
А присваивать полученное значение в поле набора данных вы можете в обработчике события AfterUpdateExecute:
Код: Выделить всё
PgStoredProc1.StoredProcName := 'f_baseuser_ins';
...
PgStoredProc1.ExecProc;
baseuser_id := PgStoredProc1.ParamByName('out_baseuser_id').AsLargeInt;
Код: Выделить всё
procedure TForm1.PgQuery1AfterUpdateExecute(Sender: TDataSet;
StatementTypes: TStatementTypes; Params: TDAParams);
begin
if stInsert in StatementTypes then
begin
Sender.FieldByName('baseuser_id').ReadOnly := False;
try
Sender.FieldByName('baseuser_id').NewValue := baseuser_id;
finally
Sender.FieldByName('baseuser_id').ReadOnly := True;
end;
end;
end;