Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / FireDac array insert / 25 сообщений из 31, страница 1 из 2
14.12.2018, 15:04
    #39747961
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Добрый день.

Исходные данные:
- Postgres
- Delphi Berlin

В Postgres написана тестовая функция (возвращающая void) вида:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
CREATE OR REPLACE FUNCTION "public"."testproc"("par" numeric)
  RETURNS "pg_catalog"."void" AS $BODY$
BEGIN
  insert into test_table (id) values (par);
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100




Необходимо из Delphi, вызвать функцию testproc в анонимном блоке с множественной вставкой.
В компоненте TFDQuery записан вызов функции в анонимном блоке:
Код: plsql
1.
2.
3.
DO $$ BEGIN
  perform testproc(:par);
end $$;



Сам вызов вставки 10 записей:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
procedure TForm1.Button5Click(Sender: TObject);
Var
  I: Integer;
begin
  TRY
    If Not FDConnection1.InTransaction Then
      FDConnection1.StartTransaction;
    FDQuery2.Params.ArraySize := 10;
    For I := 0 To 10 - 1 Do
      FDQuery2.Params[0].AsIntegers[I] := I;
    FDQuery2.Execute(10, 0);
    If FDConnection1.InTransaction Then
      FDConnection1.Commit;
    ShowMessage(IntToStr(FDQuery2.RowsAffected));
  EXCEPT
    On E: Exception Do
    Begin
      ShowMessage(E.Message);
    End;
  END;
end;



Компонент TFDQuery не определяет мой параметр :par по не известным мне причинам.

Как быть??? Как мне вызвать множественную вставку в анонимном блоке на сервере???

Вариант с явным запросом для вставки типа Insert into не предлагать, т.к. в самой функции "testproc" есть своя бизнес логика.

Всех с наступающим Новым Годом!!!!!!1
...
Рейтинг: 0 / 0
14.12.2018, 15:09
    #39747964
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
dimka07,

Что означает "не определяет" ? В чем выражается?
...
Рейтинг: 0 / 0
14.12.2018, 15:12
    #39747969
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
В редакторе компонента TFDQuery на вкладке Parameters параметр :par просто не определен, его там просто нет
...
Рейтинг: 0 / 0
14.12.2018, 15:17
    #39747971
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
dimka07,

А тебе оно надо? в редакторе? В коде, перед присвоением значений Params.Count чему равно?
...
Рейтинг: 0 / 0
14.12.2018, 15:21
    #39747974
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Равно 0
...
Рейтинг: 0 / 0
14.12.2018, 15:29
    #39747978
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
dimka07,

А если на инсерт с тем же параметром перепмсать, то не нулю? Ну дела, тут без Арефьева не разобраться.
Но ты бы не маскировал суть проблемы использованием пакетной вставки, проверь/добейся
воспроизведения на одном одиночном инсерте вообще без циклов и массивов.
...
Рейтинг: 0 / 0
14.12.2018, 15:30
    #39747979
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Также могу создавать этот параметр динамически
Код: pascal
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.
procedure TForm1.Button5Click(Sender: TObject);
Var
  I: Integer;
begin
  TRY
    If Not FDConnection1.InTransaction Then
      FDConnection1.StartTransaction;
    ShowMessage(fdquery2.Params.Count.ToString);
    With FDQuery2.Params Do
    Begin
      Clear;
      With Add Do
      Begin
        Name := 'par';
        ParamType := ptInput;
        DataType := ftInteger;
      End;
    End;
    ShowMessage(fdquery2.Params.Count.ToString);
    FDQuery2.Params.ArraySize := 10;
    For I := 0 To 10 - 1 Do
      FDQuery2.Params[0].AsIntegers[I] := I;
    FDQuery2.Execute(10, 0);
    If FDConnection1.InTransaction Then
      FDConnection1.Commit;
    ShowMessage(IntToStr(FDQuery2.RowsAffected));
  EXCEPT
    On E: Exception Do
    Begin
      ShowMessage(E.Message);
    End;
  END;
end;



В этом случае количество параметров равно 1, но при выполнении запроса появляется ошибка:
Ошибка синтаксиса (примерное положение: ":")
...
Рейтинг: 0 / 0
14.12.2018, 15:44
    #39747992
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
dimka07,

Ты можешь "раздеть" пример, оставив ровно одну вставку с одним параметром без циклов и массивов?
И как он будет выполняться, если присвоение значения параметру закомментировать?
...
Рейтинг: 0 / 0
14.12.2018, 15:51
    #39748002
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
с простым запросом на вставку работает
Код: plsql
1.
2.
3.
DO $$ BEGIN
  perform testproc(1001);
end $$;
...
Рейтинг: 0 / 0
14.12.2018, 17:22
    #39748047
Dmitry Arefiev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
https://www.postgresql.org/docs/9/sql-do.html:
авторThe code block is treated as though it were the body of a function with no parameters , returning void. It is parsed and executed a single time.
...
Рейтинг: 0 / 0
14.12.2018, 17:36
    #39748064
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Dmitry Arefiev,

Дмитрий, когда мы использовали Oracle, то с помощью FireDac, мы спокойно использовали анонимные блоки и выполняли вставку в массиве.
Может быть Вы подскажете в этом случае обходной путь для Postgres с использованием firedac???
...
Рейтинг: 0 / 0
14.12.2018, 17:40
    #39748068
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Dmitry Arefiev,

Дмитрий, когда мы использовали Oracle, то с помощью FireDac, мы спокойно использовали анонимные блоки и выполняли вставку в массиве.
Может быть Вы подскажете в этом случае обходной путь для Postgres с использованием firedac???
...
Рейтинг: 0 / 0
14.12.2018, 17:52
    #39748080
Dmitry Arefiev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
А зачем там вообще анонимный блок, который содержит единственный вызов функции ? Либо вызывать эту функцию, либо напрямую вызывать INSERT. Последнее лучше, с точки зрения производительности.
...
Рейтинг: 0 / 0
14.12.2018, 20:48
    #39748175
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
На клиенте кэшируются в словарь значения для вставки в БД, в порядке от 100 до 5000 записей.

По требованию клиента - событию, эти данные должны вставиться в БД Postgres. Из Вашего примера со студией Array DML, операция Insert работает очень производительно. Но в моей случае мне нужно вызвать функцию в БД для вставки. В теле функции перед самой вставкой есть определенная бизнес-логика, так что напрямую вызвать Insert я не могу.

Вот у меня и возник вопрос, как вызвать функцию из Базы для вставки. Через FDStoredProc параметр определяется:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
FDStoredProc2.Params.ArraySize := 10000;
    For I := 0 To 10000 - 1 Do
      FDStoredProc2.ParamByName('par').AsSmallInts[I] := I;
    FDStoredProc2.Execute(10000, 0);
    If FDConnection1.InTransaction Then
      FDConnection1.Commit;
    ShowMessage(IntToStr(FDStoredProc2.RowsAffected));



Но в данном случае, получается не производительно, т.к. 10000 раз будет вызвана функция.

Через FDQuery параметр :par вообще не определяется:

Код: plsql
1.
2.
3.
DO $$ BEGIN
  perform testproc(:par);
end $$;
...
Рейтинг: 0 / 0
14.12.2018, 21:10
    #39748183
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
dimka07,

Ты не ответил (возможно я пропустил) на самое главное, - если с тем же текстом запроса
пытаться послать одну параметризированную запись без использования институтов Array DML,
ошибка проявляется или нет? Если да, то, имхо, это надо однозначно оформлять как багу.
...
Рейтинг: 0 / 0
14.12.2018, 21:13
    #39748185
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
С точки зрения Oracle я вызывал функцию из пакета в анонимном блоке, через FDQuery:
Код: plsql
1.
2.
3.
BEGIN
  PCKG_TEST.test_proc(:par);
END;



и сам код на Delphi:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
procedure TForm1.Button5Click(Sender: TObject);
Var
  I: Integer;
begin
  TRY
    FDQuery1.Params.ArraySize := 10000;
    For I := 0 To 10000 - 1 Do
    Begin
      FDQuery1.ParamByName('par').AsIntegers[I] := I;
    End;
    FDQuery1.Execute(10000, 0);
    ShowMessage('Yes');
    If FDConnection1.InTransaction Then
      FDConnection1.Commit;
  EXCEPT
    On E: Exception Do
    Begin
      If FDConnection1.InTransaction Then
        FDConnection1.Rollback;
      ShowMessage(E.Message);
    End;
  END;
end;




и все эти команды единым пакетом вызывались на сервере, что дает производительность. 10 000 записей вставилось за 2 секунды, с удаленного компьютера.

А с точки зрения PG у меня такое не получается
...
Рейтинг: 0 / 0
14.12.2018, 21:14
    #39748186
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Vlad F,
проявляется
...
Рейтинг: 0 / 0
14.12.2018, 21:23
    #39748193
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
dimka07Vlad F,
проявляется
Оформляйте однозначно, голосую.))
...
Рейтинг: 0 / 0
14.12.2018, 21:34
    #39748195
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Но только безо всякого упоминания FireDAC Array DML.
...
Рейтинг: 0 / 0
14.12.2018, 21:48
    #39748198
Dmitry Arefiev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Не надо мешать анонимные блоки и прочь из разных БД. Что в одной радость, то в другой может быть боль. PL/SQL блоки сильно другое по природе в отличии от PgSQL блоков. Кроме общего слова - мало общего.
...
Рейтинг: 0 / 0
14.12.2018, 21:50
    #39748201
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Дмитрий,
насколько я понимаю решения в данном вопросе нет, кроме как прямой вставкой через insert????
...
Рейтинг: 0 / 0
14.12.2018, 21:52
    #39748205
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Отец-основатель в пятницу вечером, однозначно, стоит того чтобы к нему прислушаться.))
...
Рейтинг: 0 / 0
14.12.2018, 21:54
    #39748207
Dmitry Arefiev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Прямой INSERT - лучшая производительность.
Функция - делай что хочешь внутри. Но это будет элемент за элементом.
Временная таблица - Array DML в таблицу, потом функция это перелопачивает.
ХЗ ... может FireDAC заведется от массива и засунет его в функцию ...
...
Рейтинг: 0 / 0
14.12.2018, 21:58
    #39748210
dimka07
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
Vlad F,
Если же это действительно бага, то ее решения (исправления бага) ждать долго, следующей версии RAD :)

А нам надо сдавать проект до Нового года, вот поэтому и спрашиваю у основателя и других форумчан обходное решение данной проблемы.

P.S.

С Oracle на PG считай весь функционал решения считай перевели, кроме этого момента, к большому сожалению, и если не успеем, то по шапке в качестве подарка к НГ очень сильно влетит.
...
Рейтинг: 0 / 0
14.12.2018, 22:06
    #39748217
Dmitry Arefiev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
FireDac array insert
dimka07, хех ... бага ... Ну надейся дальше.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / FireDac array insert / 25 сообщений из 31, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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