Обновить или вставить проблемы в SQL Server? - PullRequest
0 голосов
/ 30 марта 2012

В моей таблице 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 в emp_backup при следующем запуске..

Теперь моя проблема в том, что, когда я обновляю любую запись в таблице emp и пытаюсь выполнить запрос выше, он выдаёт ошибку primary key violation, что исключено.

, например.

update  EMP
set JOB='worker'
where   EMPNO=14;

Я обновляю таблицу emp после копирования записи с помощью empno 14 в таблицу emp_backup.

, когда я запускаю запрос insert into emp_backup...., я хочу, чтобы это изменение обновления отображалось в emp_backupТаблица.

Как я могу изменить вышеуказанный запрос, чтобы он копировал обновленные строки с существующим первичным ключом с emp на emp_backup.

Надеюсь, мой вопрос ясен, скажитемне, как я могу улучшить это.

Ответы [ 3 ]

1 голос
/ 30 марта 2012

для того, чтобы собрать все изменения, вам понадобится таблица истории (или аудита). Создайте в своей таблице триггер, который записывает запись, включающую в себя поле времени активности в таблицу истории с каждым изменением. затем выберите из таблицы истории, когда поле времени активности больше, чем последний резервный запрос.

thizs позволит вам собрать все обновления и удалить

0 голосов
/ 30 марта 2012

Поскольку вы используете SQL Server 2008, вы можете использовать команду MERGE .

Эта одна команда позволит вам добавлять записи, когда их нет в вашей резервной таблице, и обновлять их, чтобы они соответствовали, когда они существуют.

Вот пример из 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
0 голосов
/ 30 марта 2012

Кажется, что когда вы создали свою таблицу emp_backup, вы также создали таблицу PK в таблице EMPNO.Это не позволит вам дважды вставить одну и ту же запись emp.

Вам необходимо переосмыслить свой «резервный» план - хотите ли вы

  1. текущий аудит каждой версии каждого изменения записив таблице emp
  2. точно соответствует таблице emp?

Для 1:

  • Удалите первичный ключ из таблицы emp_backup.Это позволит скопировать в него дубликаты записей emp.Если вам нужна идемпотентность в таблице emp_backup, вы можете создать новый суррогатный PK (например, emp_backup_id int identity(1,1) и, возможно, новый столбец по умолчанию CURRENT_TIMESTAMP, чтобы помочь вам определить, какой из последних

после).При удалении вашего ПК обновленные записи могут быть «зарезервированы» как:

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 и сделать:* ??

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...