powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / MERGE WHEN MATCHED UPDATE+INSERT
7 сообщений из 7, страница 1 из 1
MERGE WHEN MATCHED UPDATE+INSERT
    #40078009
Двоичник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Помогите пожалуйста разобраться, не могу совладать со скриптом

Пытаюсь соблюсти версионирование записей для мастер системы системы в своем ХД.

Таким образом вынимаю данные из таблицы, и складываю в свою БД. Но и добавляю признаки.
В мастерсистеме запись сохраняет свой идентификатор, но при этом актуализирует поле версии, удаляя предыдущую запись.

Моя задача далее сделать MERGE по основному признаку, и по косвенному понимать, изменилась ли запись

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
declare @m bigint select @m = IsNull(max(_Version), 0) from TTarget
declare @ts datetime = getdate()


MERGE INTO TTarget AS Target  
USING (select 
       [_IDRRef]
      ,[_Version]      
      ,[crt]
      ,[upd]
      ,[del]
      ,[cud]   -- 0 - created, 1 - updated, 2 - deleted
from TSource where [_Version] > @m)  
       AS Source (
       [_IDRRef]
      ,[_Version]      
      ,[crt]
      ,[upd]
      ,[del]
      ,[cud]
	   )  
ON  Target.[_IDRRef] = Source.[_IDRRef]




И вот далее я делаю MERGE

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
WHEN MATCHED and Target.[_Version] != Source.[_Version] 
THEN UPDATE SET upd = @ts, cud = 1


 
WHEN NOT MATCHED BY SOURCE	--отсутствуют в источнике, но есть в Target - помечаем как удаленные 
THEN UPDATE SET del = @ts, cud = 2

WHEN NOT MATCHED BY TARGET	--отсутствующие в Source, для получателя новые записи
THEN INSERT (
       [_IDRRef]
      ,[_Version]
      ,[crt]
      ,[cud]
	) VALUES (
       [_IDRRef]
      ,[_Version]
      ,@ts	-- as [crt]
      ,0	-- as [cud]
	  )  
OUTPUT $action INTO #t;  




Но вот одно НО

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
WHEN MATCHED and Target.[_Version] != Source.[_Version] 
THEN 
BEGIN 
     UPDATE SET upd = @ts, cud = 1
/*    INSERT (
       [_IDRRef]
      ,[_Version]
      ,[crt]
      ,[cud]
	) VALUES (
       [_IDRRef]
      ,[_Version]
      ,@ts	-- as [crt]
      ,0	-- as [cud]
	  ) */
 
WHEN NOT MATCHED BY SOURCE	--отсутствуют в источнике, но есть в Target - помечаем как удаленные 
THEN UPDATE SET del = @ts, cud = 2

WHEN NOT MATCHED BY TARGET	--отсутствующие в Source, для получателя новые записи
THEN INSERT (
...



по сути, мне нужно, при выполненном условии, где Target.[_IDRRef] = Source.[_IDRRef], но Target.[_Version] != Source.[_Version]
то нужно старую, существующую запись в target перевести в статус архива, но при этом сделать INSERT новой записи из Source

Однако я не могу сделать одновременно
WHEN MATCHED
UPDATE ...
INSERT ...

WHEN NOT MATCHED

Как решить такую задачу?
Спасибо
...
Рейтинг: 0 / 0
MERGE WHEN MATCHED UPDATE+INSERT
    #40078019
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Двоичник
мне нужно, при выполненном условии, где Target.[_IDRRef] = Source.[_IDRRef], но Target.[_Version] != Source.[_Version]
то нужно старую, существующую запись в target перевести в статус архива, но при этом сделать INSERT новой записи из Source
В MERGE переводить в архив, с помощью предложения output складывать нужные данные в буферную таблицу.
Затем из нее делать INSERT.
...
Рейтинг: 0 / 0
MERGE WHEN MATCHED UPDATE+INSERT
    #40078021
Двоичник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

Не понимаю как сделать вставку в буферную таблицу
DELETED.* - это то ,что я проапдейтил, увел в архив
INSERTED.* - это то что не сметчилось в мерже...

хм... хотя наверное я понял посыл.
нужно смотреть из DELETED.[_Version] != Source.[_Version]
но блин, это повторно собирать сканировать таблицу "Source". Как-то не феньшуйно...

В посте я перечислил мало полей, а по факту их порядка 80...
Буферную таблицу заполнять 80. полями... Это громоздко
...
Рейтинг: 0 / 0
MERGE WHEN MATCHED UPDATE+INSERT
    #40078023
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Моя задача далее сделать MERGE из каких соображений, если это решение не подходит? Напишите BEGIN TRAN UPDATE INSERT COMMIT и не майтесь.
...
Рейтинг: 0 / 0
MERGE WHEN MATCHED UPDATE+INSERT
    #40078039
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Двоичник,

Можно вот такой изврат попробовать
Код: 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.
declare @t table (id int, v int)
insert into @t values
 (1, 1), (2, 1);

declare @s varchar(max) = '';

merge into @t t
using (values (1, 3), (2, 3)) s (id, v) on s.id = t.id
when matched and s.v <> t.v then
 update
  set
   v = s.v,
   @s += (select t.id as [@id], t.v as [@v] for xml path('matched_row'));

insert into @t
 (id, v)
 select
  b.n.value('@id', 'int'),
  b.n.value('@v', 'int')
 from
  (select cast(@s as xml)) a(x) cross apply
  a.x.nodes('matched_row') b(n);

select * from @t order by id, v;
...
Рейтинг: 0 / 0
MERGE WHEN MATCHED UPDATE+INSERT
    #40078226
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Двоичник

Однако я не могу сделать одновременно
WHEN MATCHED
UPDATE ...
INSERT ...

WHEN NOT MATCHED

Как решить такую задачу?
Спасибо



Код: 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.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
MERGE dbo.ИсторияПеремещенияСотрудниковПоДнямЛП_Таблица  AS target 
			USING (
				SELECT Дата									AS Дата,
					   Подразделение						AS Подразделение,
					   Сотрудник							AS Сотрудник,
					   Склад								AS Склад,
					   Должность							AS Должность,
					   1 									AS типВставки,
					   ДолжностьЛП							AS ДолжностьЛП
				FROM   ДляФильтрацииЗадвоенийПоДолжностям  
				WHERE  rn = 1 
			) AS source 
			ON	
				source.[Дата]		= target.[Дата]		AND
				source.[Склад]		= target.[Склад]	AND
				source.Сотрудник	= target.Сотрудник
			WHEN MATCHED AND (
			--  (target.Дата			<> source.Дата			 ) OR (target.Дата			IS NULL AND source.Дата				IS NOT NULL) OR (target.Дата			IS NOT NULL AND source.Дата				IS NULL) OR 
				(target.Подразделение	<> source.Подразделение	 ) OR (target.Подразделение	IS NULL AND source.Подразделение	IS NOT NULL) OR (target.Подразделение	IS NOT NULL AND source.Подразделение	IS NULL) OR 
			--  (target.Сотрудник		<> source.Сотрудник		 ) OR (target.Сотрудник		IS NULL AND source.Сотрудник		IS NOT NULL) OR (target.Сотрудник		IS NOT NULL AND source.Сотрудник		IS NULL) OR 
			--  (target.Склад			<> source.Склад			 ) OR (target.Склад			IS NULL AND source.Склад			IS NOT NULL) OR (target.Склад			IS NOT NULL AND source.Склад			IS NULL) OR 
				(target.Должность		<> source.Должность		 ) OR (target.Должность		IS NULL AND source.Должность		IS NOT NULL) OR (target.Должность		IS NOT NULL AND source.Должность		IS NULL) OR 
				(target.типВставки		<> source.типВставки	 ) OR (target.типВставки	IS NULL AND source.типВставки		IS NOT NULL) OR (target.типВставки		IS NOT NULL AND source.типВставки		IS NULL) OR 
				(target.ДолжностьЛП		<> source.ДолжностьЛП	 ) OR (target.ДолжностьЛП	IS NULL AND source.ДолжностьЛП		IS NOT NULL) OR (target.ДолжностьЛП		IS NOT NULL AND source.ДолжностьЛП		IS NULL) OR 
				1 = 0
			)
			THEN UPDATE SET 
			--  target.Дата				= source.Дата			,
				target.Подразделение	= source.Подразделение	,
			--  target.Сотрудник		= source.Сотрудник		,
			--  target.Склад			= source.Склад			,
				target.Должность		= source.Должность		,
				target.типВставки		= source.типВставки		,
				target.ДолжностьЛП		= source.ДолжностьЛП	
			WHEN NOT MATCHED BY TARGET THEN 
				INSERT (
					Дата,
					Подразделение,
					Сотрудник,
					Склад,
					Должность,
					типВставки,
					ДолжностьЛП
				)
				VALUES(
					Дата,
					Подразделение,
					Сотрудник,
					Склад,
					Должность,
					типВставки,
					ДолжностьЛП
				)

			;
...
Рейтинг: 0 / 0
MERGE WHEN MATCHED UPDATE+INSERT
    #40078229
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Насчет вот этого выражения:

Код: sql
1.
2.
(target.Должность		<> source.Должность		 ) OR (target.Должность		IS NULL AND source.Должность		IS NOT NULL) OR (target.Должность		IS NOT NULL AND source.Должность		IS NULL) OR 
				



1) Я прекрасно знаю о существовании ISNULL и осознанного его тут не использую
2) Если в таблице (запросе) много полей, то писать это выражение надо используя прямоугольное выделение блоков (в SSMS мышкой с нажатым ALT)
3) Если поле NOT NULL , то оптимизатор просто выкинет выражение Должность IS NOT NULL, что можно увидеть в актуальном плане
4) Запрос громоздкий, но быстрый и представляет собой одну транзакцию
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / MERGE WHEN MATCHED UPDATE+INSERT
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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