"合并"样式操作与文字值?

Kit*_*Fox 12 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
Run Code Online (Sandbox Code Playgroud)

我试图写一个存储过程,它接受Student,Grade以及StartDate和我会把它想

  1. 检查以确保这些值不重复
  2. 如果记录不重复,请插入记录
  3. 如果有现有的学生记录,并且有a 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
Run Code Online (Sandbox Code Playgroud)

这听起来像我可以使用MERGE,除了我传递文字值,我需要执行多个操作.今天早上我也有一个邪恶的头痛,似乎无法清楚地思考,所以我正在关注这个MERGE解决方案.如果有更明显的方法可以做到这一点,不要害怕指出它.

Lam*_*mak 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;
Run Code Online (Sandbox Code Playgroud)

  • 您也可以使用以下内容:USING(VALUES(@ Student,@ Grarade,@ StartDate))AS [row](学生,年级,StartDate) (4认同)

小智 16

我更喜欢以下内容,它更清晰,更易于阅读和修改.

MERGE Definition.tdSection AS Target
USING
    (SELECT *
     FROM   ( VALUES
            ( 1, 1, 'Administrator', 1, GETDATE(), NULL, Current_User, GETDATE())
             ,( 2, 1, 'Admissions', 1, GETDATE(), NULL, Current_User, GETDATE())
             ,( 3, 1, 'BOM', 1, GETDATE(), NULL, Current_User, GETDATE())
             ,( 4, 1, 'CRC', 1, GETDATE(), NULL, Current_User, GETDATE())
             ,( 5, 1, 'ICM', 1, GETDATE(), NULL, Current_User, GETDATE())
             ,( 6, 1, 'System', 1, GETDATE(), NULL,Current_User, GETDATE())
             ,( 7, 1, 'Therapy', 1, GETDATE(), NULL, Current_User, GETDATE()) 
            )
            AS s (SectionId
                  ,BusinessProcessId
                  ,Description, Sequence
                  ,EffectiveStartDate
                  ,EffectiveEndDate
                  ,ModifiedBy
                  ,ModifiedDateTime)
     ) AS Source
ON Target.SectionId = Source.SectionId
WHEN NOT MATCHED THEN
    INSERT (SectionId
           ,BusinessProcessId
           ,Description
           ,Sequence
           ,EffectiveStartDate
           ,EffectiveEndDate
           ,ModifiedBy
           ,ModifiedDateTime
           )
    VALUES (Source.SectionId
           ,Source.BusinessProcessId
           ,Source.Description
           ,Source.Sequence
           ,Source.EffectiveStartDate
           ,Source.EffectiveEndDate
           ,Source.ModifiedBy
           ,Source.ModifiedDateTime
           );
Run Code Online (Sandbox Code Playgroud)


Vin*_*ves 8

只是:

--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
);
Run Code Online (Sandbox Code Playgroud)