powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Вопрос по MERGE
8 сообщений из 8, страница 1 из 1
Вопрос по MERGE
    #39844573
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет всем.

FB 2.5.9

Создадим и заполним таблицу:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
create table T (
    ID   integer not null,
    INC  integer
);

alter table T
  add constraint PK_T primary key ( ID );

insert into T ( ID )
       values ( 1 );
insert into T ( ID )
       values ( 2 );
insert into T ( ID )
       values ( 3 );
commit;


Данные в таблице T:
Код: powershell
1.
2.
3.
4.
ID	INC
1	null
2	null
3	null



Создадим хранимую процедуру:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
set term ^ ;
create procedure P_INC
returns ( INC integer )
as
begin
-- процедура в рамках транзакции возвращает монтонно возрастающую последовательность
  RDB$SET_CONTEXT( 'USER_TRANSACTION', 'INC', cast( coalesce( RDB$GET_CONTEXT( 'USER_TRANSACTION', 'INC'), 0 ) as integer ) + 1 );
  INC = RDB$GET_CONTEXT( 'USER_TRANSACTION', 'INC' );
  suspend;
end ^

set term ; ^



Задача состоит в том, что бы в таблице T заполнить поле INC монотонно возрастающими значениями.

Используем MERGE:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
merge into T as a
using ( select ID,
               p.INC as INC
          from T
          left join PR_INC as p on ( 1 = 1 )
         order by ID ) as b
on ( a.ID = b.ID )
when matched then
  update
     set INC = b.INC;


Результат:
Код: powershell
1.
2.
3.
4.
ID	INC
1	1
2	2
3	3



Заменим в MERGE left join на подзапрос:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
merge into T as a
using ( select ID,
             ( select INC from PR_INC ) as INC
          from T
         order by ID ) as b
on ( a.ID = b.ID )
when matched then
  update
     set INC = b.INC;


Результат (неверный):
Код: powershell
1.
2.
3.
4.
ID	INC
1	1
2	1
3	1



Чем использование в MERGE подзапроса отличается от left join?

С уважением, Polesov.
...
Рейтинг: 0 / 0
Вопрос по MERGE
    #39844582
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

тем что у тебя не коррелированный подзапрос возвращающий синглетон, для таких случаев Firebird считает что это инвариант и не перевычисляет его
...
Рейтинг: 0 / 0
Вопрос по MERGE
    #39844583
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

это можно и без MERGE проверить
...
Рейтинг: 0 / 0
Вопрос по MERGE
    #39844612
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис, спасибо.

P.S. просто MERGE выдран из контекста.
...
Рейтинг: 0 / 0
Вопрос по MERGE
    #39844619
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисне коррелированный подзапрос возвращающий синглетон, для таких случаев Firebird считает что это инвариант

Выполним запрос:
Код: sql
1.
2.
3.
4.
select ID,
     ( select INC from PR_INC ) as INC
  from T
 order by ID


Результат:
Код: powershell
1.
2.
3.
4.
ID	INC
1	1
2	2
3	3


В данном случае, если бы подзапрос считался инвариантом, то значение INC везде было бы равно 1.

Получается, что подзапрос в using MERGE и подзапрос в select - разные вещи?
...
Рейтинг: 0 / 0
Вопрос по MERGE
    #39844709
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

а ты полный аналог MERGE напиши.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT b.*
FROM T a
RIGHT JOIN (
  select ID,
     ( select INC from PR_INC ) as INC
  from T
  order by ID
) on a.ID = b.ID
...
Рейтинг: 0 / 0
Вопрос по MERGE
    #39844712
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Дениса ты полный аналог MERGE напиши.
Понятно, спасибо.
...
Рейтинг: 0 / 0
Вопрос по MERGE
    #39844717
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисне коррелированный подзапрос возвращающий синглетон, для таких случаев Firebird считает что это инвариант

Если хранимую процедуру формально скоррелировать (передача фиктивного параметра):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
create or alter procedure PR_INC ( ID integer )
returns ( INC integer)
as
begin
-- входной параметр ID нигде не используется
  RDB$SET_CONTEXT( 'USER_TRANSACTION', 'INC', cast( coalesce( RDB$GET_CONTEXT( 'USER_TRANSACTION', 'INC'), 0 ) as integer ) + 1 );
  INC = RDB$GET_CONTEXT( 'USER_TRANSACTION', 'INC' );
  suspend;
end


то с подзапросом все работает правильно:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
merge into T as a
using ( select ID,
             ( select INC from PR_INC( t.ID ) ) as INC
          from T
         order by ID ) as b
on ( a.ID = b.ID )
when matched then
  update
     set INC = b.INC;
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Вопрос по MERGE
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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