“合并”样式操作与文字值?

时间:2011-05-12 15:43:13

标签: sql merge sql-server-2008-r2

我有一张包含学生成绩关系的表格:

Student   Grade   StartDate   EndDate
   1        1    09/01/2009    NULL
   2        2    09/01/2010    NULL
   2        1    09/01/2009   06/15/2010

我正在尝试编写一个包含StudentGradeStartDate的存储过程,我希望

  1. 检查以确保这些值不重复
  2. 如果记录不重复,则插入记录
  3. 如果有现有的学生记录,并且有EndDate = NULL,则使用新记录的StartDate更新该记录。
  4. 例如,如果我调用该程序并传入1209/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解决方案。如果有更明显的方法可以做到这一点,不要害怕指出它。

3 个答案:

答案 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
);