更新或插入SQL Server中的问题?

时间:2012-03-30 04:26:50

标签: sql sql-server sql-server-2008 tsql

我的emp表中包含主键的唯一行。

select * from EMP E;

现在我已经创建了emp_backup表来备份emp表格。

insert into emp_backup
select * from emp e
where not exists (select EMPNO from emp_backup E1 where E1.EMPNO=e.EMPNO);

上述查询成功将所有行从emp复制到emp_backup,并确保当您再次运行上述查询时,它不会将现有行从emp复制到{{1下一次运行中的表。

现在我的问题是当我更新emp_backup表中的任何记录并尝试运行上面的查询时,它会给我emp的错误,但不包括。

例如。

primary key violation

我将带有update EMP set JOB='worker' where EMPNO=14; 14的记录复制到emp_backup表后更新emp表。

当我运行empno查询时,我希望此更新更改应重新进入insert into emp_backup....表。

如何修改上述查询,以便将包含现有主键的更新行从emp_backup复制到emp

我希望我的问题很明确,告诉我如何改进它。

3 个答案:

答案 0 :(得分:1)

为了收集所有更改,您需要一个历史(或审计)表。在您的表上创建一个triger,它将记录写入包含每个更改的历史记录表的活动时间字段。然后在活动时间字段大于上次备份查询时从历史表中选择。

thizs将使您能够收集所有更新插入和删除

答案 1 :(得分:0)

似乎在创建emp_backup表时,您还在EMPNO表上创建了表PK。这将阻止您两次插入相同的emp记录。

你需要重新考虑你的“备份”计划 - 你想要吗

  1. 对emp表中每个记录更改的每个版本的运行审计
  2. 是emp表的一面镜子吗?
  3. 1:

    • 将主键放在emp_backup表上。这将允许将重复的emp记录复制到其中。如果您需要emp_backup表上的幂等性,您可以创建一个新的代理PK(例如emp_backup_id int identity(1,1),可能还有一个新的CURRENT_TIMESTAMP默认列,以帮助您确定哪个是最新的

    删除PK后,更新的记录可以“备份”为:

    insert into emp_backup 
    select * from emp e 
    where exists 
      (select EMPNO 
       from emp_backup E1 
       where E1.EMPNO=e.EMPNO
       and 
       (e1.othercolumn1 <> e.othercolumn1
       or e1.othercolumn2 <> e.othercolumn2
       ...
       )
    ); . 
    

    (请注意,某些类型的列无法直接比较)

    对于2,您需要更新emp_bak表中的现有记录:

    update eb
    set eb.othercolumn1 = e.othercolumn1,
        eb.othercolumn2 = e.othercolumn2
    from emp_backup eb
        inner join emp e on eb.empno = e.empno
    where 
       eb.othercolumn1 <> e.othercolumn1
       or eb.othercolumn2 <> e.othercolumn2
       ...
    ); . 
    

    但是你的表镜像引发了一个问题,每当你想要备份时,为什么不放弃现有的emp_backup表并执行:

    insert into emp_backup 
    select * from emp e 
    

    ...

答案 2 :(得分:0)

由于您使用的是SQL Server 2008,因此可以使用MERGE命令。

这个命令将允许您在备份表中不存在时添加记录,并在它们存在时更新它们以匹配。

Here's an example from MSDN

MERGE emp_backup AS T
USING emp AS S
ON (T.EMPNO = S.EMPNO) 
WHEN NOT MATCHED BY TARGET
    THEN INSERT(EMPNO, JOB) VALUES(S.EMPNO, S.JOB)
WHEN MATCHED 
    THEN UPDATE SET T.JOB = S.JOB