Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Firebird, InterBase Новый топик    Ответить
 При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
dedRasta
Member

Откуда:
Сообщений: 142
Есть такой запрос:
+
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" в такой запрос:

+
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
22 авг 19, 10:04    [21955114]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
Симонов Денис
Member

Откуда: Рязань
Сообщений: 9831
dedRasta,

для начала надо изучить как работает suspend и больше никогда не делать таких глупостей. Самое важное твой чудесный блок изменит столько записей сколько будет отфетчено на клиента. Плюс не забыть что suspend вызывает разрыв savepoint и стабильность курсора может быть нарушена
22 авг 19, 10:22    [21955139]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
KreatorXXI
Member

Откуда: Москва
Сообщений: 783
dedRasta,

а почитать про suspend в руководстве не судьба? Написано - suspend приостанавливает выполнение всего до тех пор пока не обработаете выходные значения. В случае Execute Block это на стороне клиента. Подозреваю, что и Эксперт не поможет.
Я бы заменил Execute block на хранимку. Для отладки хотя бы.
22 авг 19, 10:26    [21955148]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
hvlad
Member

Откуда:
Сообщений: 10531
dedRasta,

fetch all ?
22 авг 19, 11:25    [21955217]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
hvlad
Member

Откуда:
Сообщений: 10531
KreatorXXI
В случае Execute Block это на стороне клиента.
Что - это ???
22 авг 19, 11:26    [21955218]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
KreatorXXI
Member

Откуда: Москва
Сообщений: 783
hvlad
KreatorXXI
В случае Execute Block это на стороне клиента.
Что - это ???


Прочитал блок "Входные и выходные параметры" для оператора Execute Block. Может чего не понял или понял не так.
22 авг 19, 12:05    [21955277]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 2929
dedRasta, вместо SUSPEND заталкивай во временную таблицу, а после выталкивай оттуда.
22 авг 19, 13:19    [21955385]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
Симонов Денис
Member

Откуда: Рязань
Сообщений: 9831
rdb_dev, dedRasta

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

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
22 авг 19, 13:26    [21955398]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
Arioch
Member

Откуда:
Сообщений: 10967
Симонов Денис
Самое важное твой чудесный блок изменит столько записей сколько будет отфетчено на клиента.


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

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


Симонов Денис
FOR SELECT
.....
  DO 
  begin
    UPDATE or INSERT
....
    INSERT


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

Заодно можно будет, если надо, избавиться от холостых update'ов
22 авг 19, 14:31    [21955521]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
rdb_dev
Member

Откуда: с болот
Сообщений: 2929
Симонов Денис
rdb_dev, dedRasta
можно как-то так
Да, норм!
Только внутри begin...end я бы сделал так:
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", которые могут уже существовать или появятся в будущем.
22 авг 19, 20:25    [21955965]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
dedRasta
Member

Откуда:
Сообщений: 142
Всем большое спасибо! Буду изучать.

hvlad, не понял насчет fetch all. Это где можно выставить?
22 авг 19, 21:03    [21955999]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
hvlad
Member

Откуда:
Сообщений: 10531
dedRasta
hvlad, не понял насчет fetch all. Это где можно выставить?
Это на клавиатуре\тулбаре
22 авг 19, 22:41    [21956069]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
dedRasta
Member

Откуда:
Сообщений: 142
hvlad
dedRasta
hvlad, не понял насчет fetch all. Это где можно выставить?
Это на клавиатуре\тулбаре

Не, пора на пенсию. Всегда маячила перед глазами эта кнопка и в голову не приходило просто мышкой на нее показать.
А с ее помощью первый вариант с SUSPEND отрабатывает без проблем:
+
План
PLAN (FB_USR INDEX (FB_USR_IDX1))
PLAN (AU NATURAL)

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

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

Но идея с GTT тоже пригодится - для отчетов о результатах импорта/экспорта.
Еще раз всем спасибо
23 авг 19, 09:50    [21956216]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
Arioch
Member

Откуда:
Сообщений: 10967
dedRasta,

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

-----------

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

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

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

а что, если бы на VIEW/GTT можно было бы сделать триггер BEFORE SELECT, который бы её и заполнял по необходимости ?
23 авг 19, 11:41    [21956333]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
Симонов Денис
Member

Откуда: Рязань
Сообщений: 9831
Arioch,

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

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

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 и выше
23 авг 19, 12:10    [21956362]     Ответить | Цитировать Сообщить модератору
 Re: При наличии "SUSPEND" в "SELECT FOR" цикле оператор "UPDATE or INSERT" не вставляет  [new]
Arioch
Member

Откуда:
Сообщений: 10967
Симонов Денис
триггер не нужен, но VIEW может быть создана на основе ХП.


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

раздельно SP и таблицу - надо будет две инструкции всегда выполнять, leaking implementation details
23 авг 19, 17:27    [21956665]     Ответить | Цитировать Сообщить модератору
Все форумы / Firebird, InterBase Ответить