SQL Server:更新现有记录并插入新记录

时间:2020-07-10 17:26:16

标签: sql sql-server sql-order-by updating

我有一张表,其中包含一组临时工,他们的合同期限可以不确定,并且可以在不同部门续签。续签到其他部门后,需要更新结束日期,并且开始日期必须是结束日期加1天。

当前输出:

+---------------------+------------------+------------------+------------------+
|         Name        |    Department    |    Start Date    |     End Date     |
+---------------------+------------------+------------------+------------------+
|         Tom         |     Finance      |    2010-08-09    |   9999-12-31     | 
+---------------------+------------------+------------------+------------------+

所需的输出

+---------------------+------------------+------------------+------------------+
|         Name        |    Department    |    Start Date    |     End Date     |
+---------------------+------------------+------------------+------------------+
|         Tom         |     Finance      |    2010-08-09    |   2010-10-10     |
|         Tom         |        HR        |    2010-10-11    |   9999-12-31     | 
+---------------------+------------------+------------------+------------------+

当前,我将现有记录保存到临时表中。然后,我对现有表的多个字段进行联接,以查看此人之前是否存在。如果此人存在,那么我将数据保存到临时表中并执行更新,然后再返回并更新主表。我不喜欢这种解决方案,而且非常复杂。有没有更好的解决方案来解决上述问题?

1 个答案:

答案 0 :(得分:0)

编辑。由于已经存在存储过程,因此可以将类似的逻辑嵌入到SP中。我创建了一个示例存储过程,该过程将使用员工姓名,更新部门,然后实施您的业务逻辑。再次,将真实的主键字段(而不是员工姓名)作为参数,否则您可能最终会更新多个记录。

ALTER PROCEDURE UpdateDepartment @EmpName VARCHAR(20), @Dept VARCHAR(20)
AS
BEGIN
    DECLARE @Changed TABLE
    (
        EmpName VARCHAR(20),
        OldDepartment VARCHAR(20),
        NewDepartment VARCHAR(20),
        StartDate DATETIME2,
        EndDate DATETIME2
    )

    UPDATE TempEmployees
    SET
        Department = @Dept
    output 
        inserted.EmpName, 
        deleted.Department, 
        inserted.Department, 
        inserted.StartDate,
        inserted.EndDate
    into @Changed
    WHERE EmpName = @EmpName

    DECLARE @OldDept VARCHAR(20);

    SELECT @OldDept = OldDepartment FROM @Changed

    UPDATE TempEmployees 
    SET 
        EndDate = CURRENT_TIMESTAMP,
        Department = @OldDept
    WHERE EmpName = @EmpName;

    INSERT INTO TempEmployees 
    SELECT
        EmpName,
        NewDepartment,
        DATEADD(DAY, 1, CURRENT_TIMESTAMP),
        '99991231'
    FROM @Changed

END

一种选择是使用触发器,并利用UPDATE语句生成的输出表。运行UPDATE语句时,将生成inserteddeleted输出表,其中详细说明了记录的前状态和后状态。

请参见下面的代码,并尝试为您的应用程序对其进行修改。请注意,此触发器的当前版本使用Employee Name作为更新谓词的一部分。如果您有一个以上特定雇员姓名的记录,那么所有记录都会被更新。因此,最好在表上使用真实的主键字段,以确保仅更新 个记录。

CREATE TRIGGER TempEmployeeMovedDepartment
ON TempEmployees
AFTER UPDATE 
AS
BEGIN
    SET NOCOUNT ON;

    IF UPDATE(Department)
    BEGIN
        --Update the End Date for the Current Record. In this case, I'm using the EmpName
        --field to denote the record to update. Presumably, you'd have an actual Primary Key
        DECLARE @PK VARCHAR(20);
        DECLARE @OldDept VARCHAR(20);

        SELECT @PK = EmpName, @OldDept = Department FROM deleted;

        UPDATE TempEmployees 
        SET 
            EndDate = CURRENT_TIMESTAMP,
            Department = @OldDept
        WHERE EmpName = @PK;

        INSERT INTO TempEmployees 
        SELECT
            EmpName,
            Department,
            DATEADD(DAY, 1, CURRENT_TIMESTAMP),
            '99991231'
        FROM inserted
    END
END