powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
16 сообщений из 16, страница 1 из 1
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852532
dedRasta
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть такой запрос:
Код: plsql
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.
execute block
returns (
    iID      BIGINT,
    vFNAME   VARCHAR(250),
    vLNAME   VARCHAR(250),
    vMNAME   VARCHAR(250)
    )
as
begin
FOR SELECT
    AU.HOSTUSERID,
    AU.FIRSTNAME,
    LASTNAME,
    AU.MIDDLENAME
from EX_ALL_USER_KEYS AU
into  :iID, :VFNAME, :VLNAME, :VMNAME
 DO begin
--    suspend;
    UPDATE or INSERT into FB_USR
    (        ID,  FNAME,    LNAME,   SNAME, DIST_DAT)
    values (:IID, :vFNAME, :vLNAME, :vMNAME, CAST('21.08.2019' AS DATE))
    MATCHING (ID, FNAME,    LNAME,   SNAME);
--    suspend;
  end
end


Выполняем его в IBExpert.
Если убрать "SUSPEND" - выполняется нормально:

План
PLAN (FB_USR INDEX (FB_USR_IDX1))
PLAN (AU NATURAL)

932 записей было обновлено в таблице FB_USR

570 записей было добавлено в таблицу FB_USR



Если оставить "SUSPEND" до или после - выполняется только UPDATE

PLAN (FB_USR INDEX (FB_USR_IDX1))
PLAN (AU NATURAL)

159 записей было обновлено в таблице FB_USR


А вот если вставить "SUSPEND" в такой запрос:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
execute block
as
declare variable iID BIGINT;
declare variable vFNAME varchar(250);
declare variable vLNAME varchar(250);
declare variable vMNAME varchar(250);
begin
FOR SELECT
    AU.HOSTUSERID,
    AU.FIRSTNAME,
    LASTNAME,
    AU.MIDDLENAME
from EX_ALL_USER_KEYS AU
into  :iID, :VFNAME, :VLNAME, :VMNAME
 DO begin
    UPDATE or INSERT into FB_USR
    (        ID,  FNAME,    LNAME,   SNAME )
    values (:IID, :vFNAME, :vLNAME, :vMNAME)
    MATCHING (ID, FNAME,    LNAME,   SNAME );
    suspend;
  end
end



то получим

План
PLAN (FB_USR INDEX (FB_USR_IDX1))
PLAN (AU NATURAL)

1 записей было обновлено в таблице FB_USR


Без "SUSPEND" работает нормально.


Firebird 2.5.9.27139 (релиз) superserver
Windows 7
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852547
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dedRasta,

для начала надо изучить как работает suspend и больше никогда не делать таких глупостей. Самое важное твой чудесный блок изменит столько записей сколько будет отфетчено на клиента. Плюс не забыть что suspend вызывает разрыв savepoint и стабильность курсора может быть нарушена
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852552
KreatorXXI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dedRasta,

а почитать про suspend в руководстве не судьба? Написано - suspend приостанавливает выполнение всего до тех пор пока не обработаете выходные значения. В случае Execute Block это на стороне клиента. Подозреваю, что и Эксперт не поможет.
Я бы заменил Execute block на хранимку. Для отладки хотя бы.
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852578
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dedRasta,

fetch all ?
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852579
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KreatorXXIВ случае Execute Block это на стороне клиента.Что - это ???
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852607
KreatorXXI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladKreatorXXIВ случае Execute Block это на стороне клиента.Что - это ???

Прочитал блок "Входные и выходные параметры" для оператора Execute Block. Может чего не понял или понял не так.
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852681
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dedRasta, вместо SUSPEND заталкивай во временную таблицу, а после выталкивай оттуда.
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852688
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev, dedRasta

можно как-то так

Код: sql
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.
execute block
returns (
    iID      BIGINT,
    vFNAME   VARCHAR(250),
    vLNAME   VARCHAR(250),
    vMNAME   VARCHAR(250)
    )
as
begin
  DELETE FROM GTT_TABLE;
  FOR SELECT
      AU.HOSTUSERID,
      AU.FIRSTNAME,
      LASTNAME,
      AU.MIDDLENAME
    from EX_ALL_USER_KEYS AU
    into  :iID, :VFNAME, :VLNAME, :VMNAME
  DO 
  begin
    UPDATE or INSERT into FB_USR
    (        ID,  FNAME,    LNAME,   SNAME, DIST_DAT)
    values (:IID, :vFNAME, :vLNAME, :vMNAME, CAST('21.08.2019' AS DATE))
    MATCHING (ID, FNAME,    LNAME,   SNAME);

    INSERT INTO GTT_TABLE(iID, vFNAME, vLNAME, vMNAME)
    VALUES (:iID, :vFNAME, :vLNAME, :vMNAME);
  end
  FOR SELECT iID, vFNAME, vLNAME, vMNAME
         FROM GTT_TABLE
         INTO iID, vFNAME, vLNAME, vMNAME
  DO SUSPEND;
end
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852746
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисСамое важное твой чудесный блок изменит столько записей сколько будет отфетчено на клиента.

Возможно, это и хорошо.

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


Симонов Денис
Код: sql
1.
2.
3.
4.
5.
6.
7.
FOR SELECT
.....
  DO 
  begin
    UPDATE or INSERT
....
    INSERT



Бррр. Понимаю, что на скорую руку. Но всё же лучше от цикла избавиться вообще. Сначала заполняем GTT одной командой insert, потом модифицируем таблицу одной командой MERGE.

Заодно можно будет, если надо, избавиться от холостых update'ов
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39852986
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисrdb_dev, dedRasta
можно как-то такДа, норм!
Только внутри begin...end я бы сделал так:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
UPDATE OR INSERT INTO fb_user (id, fname, lname, sname, dist_dat)
  VALUES (:iid, :vfname, :vlname, :vmname, Cast('21.08.2019' AS DATE))
  MATCHING (id, fname, lname, sname)
  RETURNING id, fname, lname, mname, dist_dat
  INTO: iid, vfname, vlname, vmname, dist_dat;

INSERT INTO gtt_table (id, fname, lname, sname, dist_dat)
  VALUES (:iid, :vfname, :vlname, :vmname, :dist_date);

Чтобы потом долго и упорно не искать концы на случай внесения изменения триггерами таблицы "fb_user", которые могут уже существовать или появятся в будущем.
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39853005
dedRasta
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем большое спасибо! Буду изучать.

hvlad, не понял насчет fetch all. Это где можно выставить?
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39853026
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dedRastahvlad, не понял насчет fetch all. Это где можно выставить?Это на клавиатуре\тулбаре
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39853114
dedRasta
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
hvladdedRastahvlad, не понял насчет fetch all. Это где можно выставить?Это на клавиатуре\тулбаре
Не, пора на пенсию. Всегда маячила перед глазами эта кнопка и в голову не приходило просто мышкой на нее показать.
А с ее помощью первый вариант с SUSPEND отрабатывает без проблем:
План
PLAN (FB_USR INDEX (FB_USR_IDX1))
PLAN (AU NATURAL)

932 записей было обновлено в таблице FB_USR

570 записей было добавлено в таблицу FB_USR

Но идея с GTT тоже пригодится - для отчетов о результатах импорта/экспорта.
Еще раз всем спасибо
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39853183
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dedRasta,

можно ещё в настройках IBE сделать, чтобы всегда был fetch all, но это на любителя, на больших запросах... сам понимаешь.

-----------

кстати о "сумасшедших идеях" и об уходе от императивного стиля назад к декларативному.

исходный код Расты-Симонова - это два цикла FOR SELECT, с итерацией по одной строчке

мой вариант - INSERT+MERGE, но потом снова цикл, иначе данные из selectable SP/EB не вытолкнешь

а что, если бы на VIEW/GTT можно было бы сделать триггер BEFORE SELECT, который бы её и заполнял по необходимости ?
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39853198
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch,

триггер не нужен, но VIEW может быть создана на основе ХП.

При некоторых условиях можно и вообще без GTT обойтись
MERGE +

Код: sql
1.
2.
3.
4.
5.
FOR SELECT 
  ID,  FNAME,  LNAME,   SNAME, DIST_DAT
FROM FB_USR
WHERE RDB$RECORD_VERSION = CURRENT_TRANSACTION
INTO ...



1. блок должен выполняться в транзакции только один раз, новое выполнение требует новую транзакцию
2. выборка из FB_USR будет использовать NATURAL
3. требуется Firebird 3.0 и выше
...
Рейтинг: 0 / 0
При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
    #39853383
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денистриггер не нужен, но VIEW может быть создана на основе ХП.

VIEW = SELECT FROM SP: а как с материализацией? создавать постоянную таблицу и проверяйт её в процедуре? оптимизатору не понравится на join'ах и громоздко

раздельно SP и таблицу - надо будет две инструкции всегда выполнять, leaking implementation details
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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