存储过程比较两个表和 Insert/Update 值
Stored Procedure Compare Two Tables And Insert/Update Value
假设我有2个table: Table A, Table B
Table A
的示例记录
StuId
ExamId
Name
Listening
Writing
Reading
TotalMarks
Status
Remarks
S001
EX123
Amanda
70
85
88
81
(null)
(null)
S002
EX150
Elisa
60
74
52
62
(null)
(null)
Table B
的样本记录
StuId
ExamId
Name
Listening
Writing
Reading
TotalMarks
S001
EX123
Amanda
70
85
88
81
S002
EX150
Elisa
65
74
52
64
S003
EX213
Derick
80
78
92
83
S004
EX334
Jonathan
43
65
69
59
我想在存储过程中做的事情:
- 比较
StuId
& ExamId
在 Table B 是否存在于 Table A?
- 如果存在,将值插入到
Status
= 'remain'
- 如果不存在,则向TableB插入记录,并且
Status
= 'new'
- 比较
Listening, Writing, Reading, TotalMarks
的分数
- 如果在Table A中标记与Table B相同,则将值插入
Remarks
= 'none'
- 如果 Table A 中的
Listening
标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入Remarks
= 'Ori lis % = ' + (来自 Table A 的标记) + '新列表 % = ' + (来自 Table B 的标记)
- 如果 Table A 中的
Writing
标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入value to Remarks
= Remarks + 'Ori wri % = ' + (marks from Table A) + ' New wri % = ' + (marks from Table B)
- 如果 Table A 中的
Reading
标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入value to Remarks
= Remarks + 'Ori rea % = ' + (marks from Table A) + ' New rea % = ' + (marks from Table B)
- TotalMarks 相同
EXEC 存储过程后 Table A 的预期结果
StuId
ExamId
Name
Listening
Writing
Reading
TotalMarks
Status
Remarks
S001
EX123
Amanda
70
85
88
81
remain
none
S002
EX150
Elisa
65
74
52
64
remain
Ori lis % = 60 New list % = 65 Ori ttl % = 62 New ttl % = 64
S003
EX213
Derick
80
78
92
83
new
none
S004
EX334
Jonathan
43
65
69
59
new
none
我设法做到的:
- 插入新记录到 Table A
- 插入状态=新
代码:
DECLARE @StatusRem VARCHAR(20) = 'remain'
DECLARE @StatusNew VARCHAR(20) = 'new'
DECLARE @Remarks VARCHAR(100) = ' '
INSERT INTO Table_A (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status, Remarks)
SELECT
StuId, ExamId, Name, Listening, Writing, Reading,
TotalMarks, @StatusNew, @Remarks
FROM
Table_B b
LEFT JOIN
table_A a ON b.StuId = a.StuId
AND b.ExamId = a.ExamId
WHERE
a.StuId IS NULL AND a.ExamId IS NULL
有人知道我应该如何继续插入 'remain' 状态、比较和更新标记并插入备注吗?
感谢您的帮助!
为了讨论和演示,我们必须有表格,而不是关于表格的故事。下次您应该发布查询以创建表并插入示例数据,如下所示
-- DDL+DML
use tempdb
GO
DROP TABLE IF EXISTS TA
GO
CREATE TABLE TA (
StuId NVARCHAR(100),
ExamId NVARCHAR(100),
Name NVARCHAR(100),
Listening INT ,
Writing INT ,
Reading INT ,
TotalMarks INT ,
Status NVARCHAR(100),
Remarks NVARCHAR(MAX)
)
GO
INSERT TA (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status, Remarks)
VALUES
('S001', 'EX123', 'Amanda', 70, 85, 88, 81, null, null),
('S002', 'EX150', 'Elisa' , 60, 74, 52, 62, null, null)
GO
DROP TABLE IF EXISTS TB
GO
CREATE TABLE TB (
StuId NVARCHAR(100),
ExamId NVARCHAR(100),
Name NVARCHAR(100),
Listening INT ,
Writing INT ,
Reading INT ,
TotalMarks INT
)
GO
INSERT TB (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks)
VALUES
('S001', 'EX123', 'Amanda' , 70, 85, 88, 81),
('S002', 'EX150', 'Elisa' , 65, 74, 52, 64),
('S003', 'EX213', 'Derick' , 80, 78, 92, 83),
('S004', 'EX334', 'Jonathan', 43, 65, 69, 59)
GO
SELECT * FROM TA
SELECT * FROM TB
GO
现在我们可以开始讨论并提出解决方案
1.Compare StuId & ExamId in Table B exists in Table A?
MERGE dbo.TA AS tgt
USING (
SELECT StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks
FROM TB
) as src
ON (tgt.StuId = src.StuId and tgt.ExamId = src.ExamId )
WHEN MATCHED
THEN UPDATE SET tgt.Status = 'remain'
WHEN NOT MATCHED
THEN INSERT (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status)
VALUES (src.StuId, src.ExamId, src.Name, src.Listening, src.Writing, src.Reading, src.TotalMarks, 'new')
OUTPUT Inserted.StuId, Inserted.ExamId, Inserted.Name, Inserted.Listening, Inserted.Writing, Inserted.Reading, Inserted.TotalMarks, Inserted.Status;
GO
- Compare marks of Listening, Writing, Reading, TotalMarks
如果您想同时获得这两个条件,那么您可以使用以下使用单个 MERGE 查询的完整解决方案
MERGE dbo.TA AS tgt
USING (
SELECT StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks
FROM TB
) as src
ON (tgt.StuId = src.StuId and tgt.ExamId = src.ExamId )
WHEN MATCHED
THEN UPDATE SET tgt.Status = 'remain',
tgt.Remarks = CASE
WHEN src.Listening = tgt.Listening and src.Writing = tgt.Writing and src.Reading = tgt.Reading and src.TotalMarks = tgt.TotalMarks THEN 'none'
ELSE IIF(src.Listening != tgt.Listening ,'Ori lis % = ' + CONVERT(NVARCHAR(100),src.Listening ) + '; New lis % = ' + CONVERT(NVARCHAR(100),tgt.Listening ) + ';','')
+ IIF(src.Writing != tgt.Writing ,'Ori wri % = ' + CONVERT(NVARCHAR(100),src.Writing ) + '; New wri % = ' + CONVERT(NVARCHAR(100),tgt.Writing ) + ';','')
+ IIF(src.Reading != tgt.Reading ,'Ori rea % = ' + CONVERT(NVARCHAR(100),src.Reading ) + '; New rea % = ' + CONVERT(NVARCHAR(100),tgt.Reading ) + ';','')
+ IIF(src.TotalMarks != tgt.TotalMarks,'Ori Ttl % = ' + CONVERT(NVARCHAR(100),src.TotalMarks) + '; New Ttl % = ' + CONVERT(NVARCHAR(100),tgt.TotalMarks) + ';','')
END
WHEN NOT MATCHED
THEN INSERT (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status)
VALUES (src.StuId, src.ExamId, src.Name, src.Listening, src.Writing, src.Reading, src.TotalMarks, 'new')
OUTPUT Inserted.StuId, Inserted.ExamId, Inserted.Name,
Inserted.Listening as Listening_Ori , src.Listening as Listening_New ,
Inserted.Writing as Writing_Ori , src.Writing as Writing_New ,
Inserted.Reading as Inserted_Ori , src.Reading as Inserted_New ,
Inserted.TotalMarks as TotalMarks_Ori , src.TotalMarks as TotalMarks_New ,
Inserted.Status, Inserted.Remarks;
GO
SELECT * FROM TA
SELECT * FROM TB
GO
假设我有2个table: Table A, Table B
Table A
的示例记录StuId | ExamId | Name | Listening | Writing | Reading | TotalMarks | Status | Remarks |
---|---|---|---|---|---|---|---|---|
S001 | EX123 | Amanda | 70 | 85 | 88 | 81 | (null) | (null) |
S002 | EX150 | Elisa | 60 | 74 | 52 | 62 | (null) | (null) |
Table B
的样本记录StuId | ExamId | Name | Listening | Writing | Reading | TotalMarks |
---|---|---|---|---|---|---|
S001 | EX123 | Amanda | 70 | 85 | 88 | 81 |
S002 | EX150 | Elisa | 65 | 74 | 52 | 64 |
S003 | EX213 | Derick | 80 | 78 | 92 | 83 |
S004 | EX334 | Jonathan | 43 | 65 | 69 | 59 |
我想在存储过程中做的事情:
- 比较
StuId
&ExamId
在 Table B 是否存在于 Table A?- 如果存在,将值插入到
Status
= 'remain' - 如果不存在,则向TableB插入记录,并且
Status
= 'new'
- 如果存在,将值插入到
- 比较
Listening, Writing, Reading, TotalMarks
的分数- 如果在Table A中标记与Table B相同,则将值插入
Remarks
= 'none' - 如果 Table A 中的
Listening
标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入Remarks
= 'Ori lis % = ' + (来自 Table A 的标记) + '新列表 % = ' + (来自 Table B 的标记) - 如果 Table A 中的
Writing
标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入value toRemarks
= Remarks + 'Ori wri % = ' + (marks from Table A) + ' New wri % = ' + (marks from Table B) - 如果 Table A 中的
Reading
标记与 Table B 中的标记不同,则将标记从 Table B 更新为 Table A,并插入value toRemarks
= Remarks + 'Ori rea % = ' + (marks from Table A) + ' New rea % = ' + (marks from Table B) - TotalMarks 相同
- 如果在Table A中标记与Table B相同,则将值插入
EXEC 存储过程后 Table A 的预期结果
StuId | ExamId | Name | Listening | Writing | Reading | TotalMarks | Status | Remarks |
---|---|---|---|---|---|---|---|---|
S001 | EX123 | Amanda | 70 | 85 | 88 | 81 | remain | none |
S002 | EX150 | Elisa | 65 | 74 | 52 | 64 | remain | Ori lis % = 60 New list % = 65 Ori ttl % = 62 New ttl % = 64 |
S003 | EX213 | Derick | 80 | 78 | 92 | 83 | new | none |
S004 | EX334 | Jonathan | 43 | 65 | 69 | 59 | new | none |
我设法做到的:
- 插入新记录到 Table A
- 插入状态=新
代码:
DECLARE @StatusRem VARCHAR(20) = 'remain'
DECLARE @StatusNew VARCHAR(20) = 'new'
DECLARE @Remarks VARCHAR(100) = ' '
INSERT INTO Table_A (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status, Remarks)
SELECT
StuId, ExamId, Name, Listening, Writing, Reading,
TotalMarks, @StatusNew, @Remarks
FROM
Table_B b
LEFT JOIN
table_A a ON b.StuId = a.StuId
AND b.ExamId = a.ExamId
WHERE
a.StuId IS NULL AND a.ExamId IS NULL
有人知道我应该如何继续插入 'remain' 状态、比较和更新标记并插入备注吗?
感谢您的帮助!
为了讨论和演示,我们必须有表格,而不是关于表格的故事。下次您应该发布查询以创建表并插入示例数据,如下所示
-- DDL+DML
use tempdb
GO
DROP TABLE IF EXISTS TA
GO
CREATE TABLE TA (
StuId NVARCHAR(100),
ExamId NVARCHAR(100),
Name NVARCHAR(100),
Listening INT ,
Writing INT ,
Reading INT ,
TotalMarks INT ,
Status NVARCHAR(100),
Remarks NVARCHAR(MAX)
)
GO
INSERT TA (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status, Remarks)
VALUES
('S001', 'EX123', 'Amanda', 70, 85, 88, 81, null, null),
('S002', 'EX150', 'Elisa' , 60, 74, 52, 62, null, null)
GO
DROP TABLE IF EXISTS TB
GO
CREATE TABLE TB (
StuId NVARCHAR(100),
ExamId NVARCHAR(100),
Name NVARCHAR(100),
Listening INT ,
Writing INT ,
Reading INT ,
TotalMarks INT
)
GO
INSERT TB (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks)
VALUES
('S001', 'EX123', 'Amanda' , 70, 85, 88, 81),
('S002', 'EX150', 'Elisa' , 65, 74, 52, 64),
('S003', 'EX213', 'Derick' , 80, 78, 92, 83),
('S004', 'EX334', 'Jonathan', 43, 65, 69, 59)
GO
SELECT * FROM TA
SELECT * FROM TB
GO
现在我们可以开始讨论并提出解决方案
1.Compare StuId & ExamId in Table B exists in Table A?
MERGE dbo.TA AS tgt
USING (
SELECT StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks
FROM TB
) as src
ON (tgt.StuId = src.StuId and tgt.ExamId = src.ExamId )
WHEN MATCHED
THEN UPDATE SET tgt.Status = 'remain'
WHEN NOT MATCHED
THEN INSERT (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status)
VALUES (src.StuId, src.ExamId, src.Name, src.Listening, src.Writing, src.Reading, src.TotalMarks, 'new')
OUTPUT Inserted.StuId, Inserted.ExamId, Inserted.Name, Inserted.Listening, Inserted.Writing, Inserted.Reading, Inserted.TotalMarks, Inserted.Status;
GO
- Compare marks of Listening, Writing, Reading, TotalMarks
如果您想同时获得这两个条件,那么您可以使用以下使用单个 MERGE 查询的完整解决方案
MERGE dbo.TA AS tgt
USING (
SELECT StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks
FROM TB
) as src
ON (tgt.StuId = src.StuId and tgt.ExamId = src.ExamId )
WHEN MATCHED
THEN UPDATE SET tgt.Status = 'remain',
tgt.Remarks = CASE
WHEN src.Listening = tgt.Listening and src.Writing = tgt.Writing and src.Reading = tgt.Reading and src.TotalMarks = tgt.TotalMarks THEN 'none'
ELSE IIF(src.Listening != tgt.Listening ,'Ori lis % = ' + CONVERT(NVARCHAR(100),src.Listening ) + '; New lis % = ' + CONVERT(NVARCHAR(100),tgt.Listening ) + ';','')
+ IIF(src.Writing != tgt.Writing ,'Ori wri % = ' + CONVERT(NVARCHAR(100),src.Writing ) + '; New wri % = ' + CONVERT(NVARCHAR(100),tgt.Writing ) + ';','')
+ IIF(src.Reading != tgt.Reading ,'Ori rea % = ' + CONVERT(NVARCHAR(100),src.Reading ) + '; New rea % = ' + CONVERT(NVARCHAR(100),tgt.Reading ) + ';','')
+ IIF(src.TotalMarks != tgt.TotalMarks,'Ori Ttl % = ' + CONVERT(NVARCHAR(100),src.TotalMarks) + '; New Ttl % = ' + CONVERT(NVARCHAR(100),tgt.TotalMarks) + ';','')
END
WHEN NOT MATCHED
THEN INSERT (StuId, ExamId, Name, Listening, Writing, Reading, TotalMarks, Status)
VALUES (src.StuId, src.ExamId, src.Name, src.Listening, src.Writing, src.Reading, src.TotalMarks, 'new')
OUTPUT Inserted.StuId, Inserted.ExamId, Inserted.Name,
Inserted.Listening as Listening_Ori , src.Listening as Listening_New ,
Inserted.Writing as Writing_Ori , src.Writing as Writing_New ,
Inserted.Reading as Inserted_Ori , src.Reading as Inserted_New ,
Inserted.TotalMarks as TotalMarks_Ori , src.TotalMarks as TotalMarks_New ,
Inserted.Status, Inserted.Remarks;
GO
SELECT * FROM TA
SELECT * FROM TB
GO