2009-04-12 2 views
10

, поэтому у меня есть старая база данных, в которую я перехожу на новую. Новый имеет немного другую, но в основном совместимую схему. Кроме того, я хочу перенумеровать все таблицы с нуля.TSQL: UPDATE с INSERT IN SELECT FROM

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

например, я выбираю из MV5.Posts и вставляет в MV6.Posts. После вставки я получаю идентификатор новой строки в MV6.Posts и обновляю ее в старом поле MV5.Posts.MV6ID.

Есть ли способ сделать это ОБНОВЛЕНИЕ через INSERT INTO SELECT FROM, поэтому мне не нужно обрабатывать каждую запись вручную? Я использую SQL Server 2005, dev edition.

ответ

9

Ключ миграции является сделать несколько вещей: Во-первых, ничего не делать без текущей резервной копии. Во-вторых, если ключи будут меняться, вам необходимо сохранить как старые, так и новые в новой структуре, по крайней мере, временно (навсегда, если поле ключа открыто для пользователей, потому что они могут искать его для получения старых записей).

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

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

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

Затем сделайте то же самое со связанными таблицами. Затем используйте старый значение ключа в таблице, чтобы обновить иностранных ключевых полей что-то вроде:

Update t2 
set fkfield = newkey 
from table2 t2 
join table1 t1 on t1.oldkey = t2.fkfield 

Test перенастройки, выполнив тестовые случаи и сравнивая данные с тем, что вы сохранили от до миграции. Крайне важно тщательно протестировать данные миграции или вы не можете быть уверены, что данные соответствуют старой структуре. Миграция - очень сложное действие; он не тратит время и делает это очень методично и основательно.

0

AFAIK, вы не можете обновить две разные таблицы с помощью одного оператора SQL

Однако вы можете использовать триггеры для достижения того, что вы хотите сделать.

2

Лучшее, что вы можете сделать, что я знаю, это с output clause. Предполагая, что у вас есть SQL 2005 или 2008.

USE AdventureWorks; 
GO 
DECLARE @MyTableVar table(ScrapReasonID smallint, 
          Name varchar(50), 
          ModifiedDate datetime); 
INSERT Production.ScrapReason 
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate 
     INTO @MyTableVar 
VALUES (N'Operator error', GETDATE()); 

Для обновления исходной таблицы все равно потребуется второй проход; однако это может помочь сделать вашу логику проще. Вам нужно обновить исходную таблицу? Вы можете просто сохранить новый идентификатор в третьей таблице перекрестных ссылок.

1

Хех. Я помню, как это делалось в процессе миграции.

Внесение old_id в новую таблицу упрощает обновление: вы можете просто сделать insert into newtable select ... from oldtable, - и последующее «сшивание» записей проще. В «стежке» вы либо обновите внешние ключи дочерних таблиц во вставке, выполнив подзапрос нового родителя (insert into newchild select ... (select id from new_parent where old_id = oldchild.fk) as fk, ... from oldchild), либо вы вставляете дочерние элементы и выполняете отдельное обновление для исправления внешних ключей.

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

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

Действительно, если вы правильно определили внешние ключи, вы можете использовать systables/information-schema для генерации ваших вставных утверждений.

4

Возможно, самым простым способом было бы добавить столбец на MV6.Posts для oldId, а затем вставить все записи из старой таблицы в новую таблицу. Последнее, обновить старое соответствие таблицы на oldId в новой таблице с чем-то вроде:

UPDATE mv5.posts 
SET newid = n.id 
FROM mv5.posts o, mv6.posts n 
WHERE o.id = n.oldid 

Вы можете очистить и роняйте oldId колонки потом, если вы хотите.

+0

Я действительно думаю, что оставить oldId на новом столе предпочтительнее иметь на старой таблице новый идентификатор, что делает это еще проще. – ninesided

0

Сделать колонку в MV6.Post.OldMV5Id

сделать вставки в MV6.Post выберите .. из MV5.Post

затем сделать обновление MV5.Post.MV6ID

1

Есть ли способ сделать это ОБНОВЛЕНИЕ через INSERT INTO SELECT FROM, поэтому мне не нужно обрабатывать каждую запись вручную?

Так как вы не хотели бы сделать это вручную , но автоматически, создать триггер MV6.Posts так, что UPDATE происходит на MV5.Posts автоматически при вставке в MV6.Posts.

И триггер может выглядеть примерно так,

create trigger trg_MV6Posts 
on MV6.Posts 
after insert 
as 
begin 
    set identity_insert MV5.Posts on 

    update MV5.Posts 
    set ID = I.ID 
    from inserted I 

    set identity_insert MV5.Posts off 
end