[英]How to execute new insert/update trigger on existing rows in SQL Server?
[英]How to insert new rows and mark existing rows with no update and updated rows in SQL Server using merge
我需要在 SQL Server 中創建一個存儲過程並實現一個 upsert 以便它將數據從臨時表(又名源)移動到最終表(又名目標)並標記每次都是新的、更新的、未更新或刪除的行一批新數據進來了。我正在使用這里解釋的合並。
問題是它正在更新沒有任何更改的行。 我的工作流程如下:
Source
移動到Target
的存儲過程我的存儲過程如下:
CREATE PROCEDURE [dbo].[upsert_with_flag_2]
AS
DECLARE @current_time AS datetime
SET @current_time = GETDATE()
MERGE [dbo].[employee] AS Target
USING [dbo].[employee_staging] AS Source
ON Source.[first_name] = Target.[first_name]
AND Source.[last_name] = Target.[last_name]
AND Source.[dob] = Target.[dob]
WHEN MATCHED
THEN
UPDATE
SET Target.[salary] = Source.[salary],
Target.[current_address] = Source.[current_address],
Target.[is_deleted] = 'Updated',
Target.[processed_date] = @current_time
WHEN NOT MATCHED BY Target
THEN
INSERT ([first_name], [last_name],
[dob], [salary],
[current_address], [is_deleted],
[processed_date])
VALUES (Source.[first_name], Source.[last_name],
Source.[dob], Source.[salary],
Source.[current_address], 'New',
@current_time);
-- After doing upsert, check for rows whose processed date is less than current date but status is new or updated, These are
-- the rows which were not present in input file. Update there status to deleted
-- QUESTION: Should we change the processed date to current date for row's whose status is deleted?
UPDATE [dbo].[employee]
SET [is_deleted] = 'deleted'
WHERE ([is_deleted] = 'New' OR [is_deleted] = 'Updated')
AND [processed_date] < @current_time
在此之后,我執行以下步驟來加載數據並獲得輸出:
--Loading the initial data
TRUNCATE TABLE [dbo].[employee_staging]
GO
INSERT INTO [dbo].[employee_staging] ([first_name],
[last_name],
[dob],
[salary],
[current_address])
VALUES ('John', 'Doe', '1995-04-28', 3000, 'Andra Pradesh'),
('Robert', 'Spenser', '1994-03-28', 1800, 'Madhya Pradesh'),
('Vikash', 'Sharma', '1996-12-20', 1400, 'Uttar Pradesh'),
('Anup', 'Soni', '1994-03-28', 1800, 'Delhi'),
('Prijan', 'Sonar', '1989-01-28', 3000, 'Himachal Pradesh')
GO
EXEC upsert_with_flag
SELECT * FROM [dbo].[employee]
--Loading the updated data
TRUNCATE TABLE [dbo].[employee_staging]
GO
INSERT INTO [dbo].[employee_staging] ([first_name], [last_name],
[dob], [salary],
[current_address])
VALUES ('Robert', 'Spenser', '1994-03-28', 2000, 'Madhya Pradesh'),
('Vikash', 'Sharma', '1996-12-20', 1400, 'Maharashtra'),
('Anup', 'Soni', '1994-03-28', 1800, 'Delhi'),
('Prijan', 'Sonar', '1989-01-28', 3000, 'Himachal Pradesh'),
('William', 'Beck', '1991-04-22', 3300, 'Karnataka'),
('Robert', 'Brownie', '1986-04-22', 5000, 'Assam')
注意第 4 行和第 5 行。 Anup 的輸入行數據沒有變化,我仍然將 [is_deleted] 列設為“已更新”。 我希望它類似於“現有”或“無變化”。
請幫助使這成為可能。 這個 upsert 邏輯是一個大管道的一部分,我們需要在新文件中更新、新建、未更新或刪除的行。 我如何實現這一目標?
您可以在更新中的 is_deleted 字段中添加 case 語句以檢查是否有任何更改。 像這樣的東西:
MERGE [dbo].[employee] as Target
USING [dbo].[employee_stagging] as Source
ON Source.[first_name] = Target.[first_name] and
Source.[last_name] = Target.[last_name] and
Source.[dob] = Target.[dob]
WHEN MATCHED
THEN
UPDATE
SET Target.[salary] = Source.[salary],
Target.[current_address] = Source.[current_address],
Target.[is_deleted] = CASE WHEN Source.salary = Target.salary
AND Source.current_address = Target.current_address THEN 'No change'
ELSE 'Updated'
END,
Target.[processed_date] = @current_time
WHEN NOT MATCHED BY Target
THEN
INSERT ([first_name],
[last_name],
[dob],
[salary],
[current_address],
[is_deleted],
[processed_date])
VALUES (Source.[first_name],
Source.[last_name],
Source.[dob],
Source.[salary],
Source.[current_address],
'New',
@current_time
);
因此,如果更新字段與暫存數據相同,則會將is_deleted更新為“無更改”,而如果更新字段已更改,則會將is_deleted更新為“已更新”。
注意:此代碼假設salary 和current_address 是不可為空的字段(字段的表定義后跟NOT NULL)。 如果有可空值,那么您應該通過將 CASE 語句替換為以下內容來處理空值:
CASE WHEN (Source.salary = Target.salary
OR Source.salary IS NULL
AND Target.salary IS NULL)
AND (Source.current_address = Target.current_address
OR Source.current_address IS NULL
AND Target.current_address IS NULL) THEN 'No change'
ELSE 'Updated'
END
(文檔在這里)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.