我有一张包含学生成绩关系的表格:
Student Grade StartDate EndDate
1 1 09/01/2009 NULL
2 2 09/01/2010 NULL
2 1 09/01/2009 06/15/2010
我正在尝试编写一个包含Student
,Grade
和StartDate
的存储过程,我希望
EndDate = NULL
,则使用新记录的StartDate
更新该记录。例如,如果我调用该程序并传入1
,2
,09/01/2010
,我最终会:
Student Grade StartDate EndDate
1 2 09/01/2010 NULL
1 1 09/01/2009 09/01/2010
2 2 09/01/2010 NULL
2 1 09/01/2009 06/15/2010
这听起来像我可以使用MERGE
,除了我传递文字值,我需要执行多个操作。今天早上我也有一个邪恶的头痛,似乎无法清楚地思考,所以我正在关注这个MERGE
解决方案。如果有更明显的方法可以做到这一点,不要害怕指出它。
答案 0 :(得分:20)
即使传递文字值,也可以使用MERGE
。以下是您的问题的示例:
CREATE PROCEDURE InsertStudentGrade(@Student INT, @Grade INT, @StartDate DATE)
AS
BEGIN;
MERGE StudentGrade AS tbl
USING (SELECT @Student AS Student, @Grade AS Grade, @StartDate AS StartDate) AS row
ON tbl.Student = Row.Student AND tbl.Grade = row.Grade
WHEN NOT MATCHED THEN
INSERT(Student, Grade, StartDate)
VALUES(row.Student, row.Grade, row.StartDate)
WHEN MATCHED AND tbl.EndDate IS NULL AND tbl.StartDate != row.StartDate THEN
UPDATE SET
tbl.StartDate = row.StartDate;
END;
答案 1 :(得分:13)
我更喜欢以下内容,它更清晰,更易于阅读和修改。
<meta>
答案 2 :(得分:5)
简单地:
--Arrange
CREATE TABLE dbo.Product
(
Id INT IDENTITY PRIMARY KEY,
Name VARCHAR(40),
)
GO
--Act
MERGE INTO dbo.Product AS Target
USING
(
--Here is the trick :)
VALUES
(1, N'Product A'),
(2, N'Product B'),
(3, N'Product C'),
(4, N'Product D')
)
AS
Source
(
Id,
Name
)
ON Target.Id= Source.Id
WHEN NOT MATCHED BY TARGET THEN
INSERT
(
Name
)
VALUES
(
Name
);