Застрял при попытке перенести две таблицы из одной БД в другую БД - PullRequest
6 голосов
/ 15 июня 2009

Я пытаюсь перенести некоторые данные из двух таблиц в старой базе данных в новую базу данных.

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

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

Есть ли какие-нибудь хитрости / рекомендации, которые помогут мне перенести данные?

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

Позволяет использовать следующую схему таблицы: -

Old Table1              New Table1
ParentId INT PK         ParentId INT PK
Name VARCHAR(50)        Name VARCHAR(50)

Old Table 2             New Table 2
ChildId INT PK          ChildId INT PK
ParentId INT FK         ParentId INT FK     
Foo VARCHAR(50)         Foo VARCHAR(50)

Значит, схемы таблиц идентичны.

Мысли

EDIT:

Для тех, кто спрашивает, RDBMS - это Sql Server 2008. Я не указывал программное обеспечение, потому что надеялся, что получу независимый ответ с помощью некоторого универсального T-Sql: P

Ответы [ 7 ]

4 голосов
/ 15 июня 2009

Я думаю, вам нужно сделать это в 2 шага.

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

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

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

EDIT:

ОК, я немного яснее о том, что вы ищете, благодаря комментариям здесь и другим ответам. Я поднял это, я думаю, что это будет делать то, что вы хотите.

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

declare @oldId as int
declare @newId as int

select @oldId = Min(ParentId) from OldTable1 

while not @oldId is null
begin
    Insert Into NewTable1 (Name)
    Select Name from OldTable1 where ParentId = @oldId

    Select @newId = SCOPE_IDENTITY()

    Insert Into NewTable2 (ParentId, Foo)
    Select @newId, Foo From OldTable2 Where ParentId = @oldId

    select @oldId = Min(ParentId) from OldTable1 where ParentId > @oldId

end

Надеюсь, это поможет,

1 голос
/ 15 июня 2009

Ну, я думаю, вам придется определить другие критерии для создания карты, например oldPK => newPK (например: Name поле равно?

Затем вы можете определить новый PK, который соответствует старому PK, и соответственно настроить ParentID.

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

РЕДАКТИРОВАТЬ : Я пытаюсь предоставить пример кода того, что я имел в виду под моим маленьким трюком. Я не изменяю исходную структуру базы данных, но сейчас я использую временную таблицу.

ОК, вы можете попробовать следующее:

1) Создайте временную таблицу, в которой хранятся значения старой таблицы, плюс она получает новый PK:

CREATE TABLE #tempTable1
(
    newPKField INT,
    oldPKField INT,
    Name VARCHAR(50)
)

2) Вставьте все значения из вашей старой таблицы во временную таблицу, вычисляя новый PK, копируя старый PK:

INSERT INTO #tempTable1
SELECT
   newPKValueHere AS newPKField,
   ParentID as oldPKField,
   Name
FROM
   Table1

3) Скопировать значения в новую таблицу

INSERT INTO NewTable1
SELECT
   newPKField as ParentId,
   Name
FROM
   #tempTable1

4) Скопируйте значения из Таблицы2 в NewTable2

INSERT INTO NewTable2
SELECT
   ChildID,
   t.newPKField AS ParentId,
   Foo
FROM 
   Table2
   INNER JOIN #tempTable1 t ON t.ParentId = parentId

Это должно сделать. Обратите внимание, что это только псевдо-код T-SQL - я не проверял это на реальной базе данных! Однако оно должно приближаться к тому, что вам нужно.

0 голосов
/ 15 июня 2009

Следующий псевдо-код должен работать для вас

CREATE TABLE newtable1
  ParentId INT PK
  OldId   INT
  Name     VARCHAR(50)

CREATE TABLE newtable2
  ChildId    INT pk
  ParentId   INT FK
  OldParent  INT
  Foo        VARCHAR(50)   

  INSERT INTO newtable1(OldId, Name)
  SELECT  ParentId, Name FROM oldtable1

  INSERT INTO newtable2(OldParent, Foo)
  SELECT ParentId, Foo FROM oldtable2

UPDATE newtable2 SET ParentId = (
  SELECT n.ParentId 
  FROM   newtable1 AS n
  WHERE  n.OldId = newtable2.oldParent
)

ALTER TABLE newtable1 DROP OldId
ALTER TABLE newtable2 DROP OldParent
0 голосов
/ 15 июня 2009

Прошлым летом у меня была прекрасная возможность глубоко погрузиться в сценарии миграции. Я использовал Oracle PL / SQL для этой задачи. Но вы не упомянули, какую технологию вы используете? Во что вы переносите данные? SQL Server? Oracle? MySQL?

Подход состоит в том, чтобы ВСТАВИТЬ строку из таблицы1, ВОЗВРАЩАЯ новый первичный ключ, сгенерированный (вероятно, SEQUENCE [в Oracle]), а затем ВСТАВИТЬ зависимые записи из таблицы 2, изменив значение их внешнего ключа на значение, возвращенное первым INSERT. , Ничего лучше не поможет, если вы не укажете, в какую СУБД вы переносите данные.

0 голосов
/ 15 июня 2009

Я не уверен из вашего вопроса, какое программное обеспечение базы данных вы используете, но если временные таблицы являются опцией, создайте временную таблицу, содержащую исходный первичный ключ table1 и новый первичный ключ table1. Затем создайте еще одну временную таблицу с копией table2, обновите копию, используя ранее созданную вами таблицу «старый ключ, новый ключ», затем используйте «вставить в select from» (или любую другую подходящую команду для вашей базы данных), чтобы скопировать исправлена ​​временная таблица в постоянное местоположение.

0 голосов
/ 15 июня 2009

Прежде всего - разве у вас не может быть какой-то временной схемы, которую можно потом отбросить ?! Это сделало бы жизнь проще. Предполагая, что вы не можете:

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

Затем вы можете создать представление, которое объединит 2 таблицы на счетчике строк, чтобы у вас был способ соотнести ключи друг с другом. Таким образом, вы будете на шаг ближе к тому, чтобы иметь возможность идентифицировать «ParentId» для новой таблицы 2.

0 голосов
/ 15 июня 2009

Можете ли вы изменить схему старых таблиц? Если это так, вы можете поместить столбец «новый идентификатор» в старые таблицы и использовать его в качестве ссылки.

Возможно, вам придется выполнить построчную вставку в новую таблицу, а затем извлечь scope_identity и сохранить его в старой таблице1. Но для table2 вы можете присоединиться к старому table1 и получить new_id.

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