Как мне работать с ограничениями FK при импорте данных с помощью мастера импорта / экспорта DTS?

16

Я пытаюсь использовать мастер импорта и экспорта SQL Server, чтобы скопировать данные из моей производственной базы данных в мою базу данных разработчиков, но когда я это делаю, происходит сбой с ошибкой «INSERT конфликтует с ограничением FOREIGN KEY», у меня более 40 таблиц с партиями из ограничений FK, есть ли какой-нибудь простой способ справиться с этим без необходимости писать сценарий с ограничением удаления / добавить constrat?

Изменить: Я только что узнал, что в веб-версии SQL Server, который я использую, DTS не позволит вам сохранять пакеты.


источник

Ответы:

28

Мне дали это решение на SQLTeam.com:

Использование:

 EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'

Затем импортируйте ваши данные

EXEC sp_msforeachtable 'ALTER TABLE ? CHECK CONSTRAINT all'

Используя этот метод, я смог импортировать все данные без проблем.

Пол Уайт 9
источник
1
sp_msforeachtablesp_MSForEachDb) не имеет документов и не поддерживается. Вы не должны / избегать его использования. Это может пропустить таблицы! См. Этот пост от @AaronBertrand -> sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/… и этот элемент подключения - (MS указывает, что это не исправит) -> connect.microsoft.com/SQLServer / обратная связь / подробности / 264677 /…
Кин Шах
После нескольких часов работы над мозгом у меня все получалось, пытаясь обойти ограничения FK для экспорта данных.
Левининя
При работе в Azure SQL V12 я получаю сообщение об ошибке «Не удалось найти хранимую процедуру sp_msforeachtable».
Дай
В любом случае не работает: /
Дуглас Гаскелл
Ты человек, который
Может Шахин Бакыр
5

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

Я чмо , но вот что я сделал:

  1. Создал БД из моего скрипта, который находился в системе контроля версий (подсказка, подсказка!). Если у вас нет скрипта, вы всегда можете сгенерировать его из существующей БД через Tasksопцию.

  2. Если какие-либо данные были автоматически вставлены в YourDB при создании, запустите DELETE FROM YourDB.dbo.tblYourTable.

    • Вы не можете обрезать данные, когда существуют внешние ключи, поэтому вы должны их использовать DELETE.
  3. Запустите это на сервере назначения: USE YourDB; EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all';

  4. Щелкните правой кнопкой мыши на YourDB в Object Explorer. Нажмите Tasks->Import Data...

  5. Первые несколько экранов мастера говорят сами за себя.

  6. На Select Source Table and Viewsэкране мастера установите флажок рядом с каждой таблицей, которую вы хотите скопировать.

  7. Для каждой строки (таблицы) на этом экране, нажмите на нее, чтобы она была выделена, а затем нажмите Edit Mappings.

  8. Для каждой строки (таблицы) нажмите / проверьте Append rows to the destination tableи Enable identity insert.

    • Если вы щелкнете по Delete rows in destination tableнему, произойдет сбой, потому что он не выдает DELETEкоманду, он выдает TRUNCATEкоманду, которая все еще конфликтует с нашими внешними ключами, потому что TRUNCATEне управляется NOCHECK CONSTRAINTранее.
  9. Пролистайте остальную часть мастера и нажмите Finish.

  10. Следите за ошибками ; предупреждения, вероятно, нормально игнорировать.

    • Если есть ошибки, нажмите Reportкнопку и просмотрите отчет. Попробуйте и разузнать , что было Success, Errorи Stopped. Вам, вероятно, нужно будет исправить причину ошибки, которая где-то скрыта в этом отчете. Тогда вам, вероятно, нужно сделать DELETE FROM YourDB.dbo.theErrorTable. Теперь нажмите кнопку «Назад» в мастере импорта и снимите флажок с каждой таблицы, которая была Success. Повторите до бесконечности.
  11. Запустите это на сервере назначения: USE YourDB; EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all';

    • Если есть ошибки ... Я не знаю, но исправьте их и попробуйте снова!
  12. Ура! :)

Спасибо всем, кто ответил на этот вопрос и вопросы, подобные этому, в сети SE, за помощь в выяснении этого.

Зак Межеевский
источник
Вы спасатель жизни
Том Гуллен
1
Большое спасибо, имел резервную копию на поврежденном диске, не мог никуда копировать БД (ошибка ввода / вывода). Таким образом, импорт данных из нескольких таблиц за один раз помог мне восстановить 99% данных.
Том Гуллен
1
Ты жжешь! Еще одна команда, которая помогла мне: EXEC sp_msforeachtable 'delete from? «; Если произошла ошибка, удалите все по закону. sp_msforeachtable сценарий здесь gist.githubusercontent.com/metaskills/893599/raw/...
Sanchitos
4

В мастере импорта вы можете сначала удалить строки и, если у вас есть поля идентификаторов, вы можете включить вставку идентификаторов, как показано ниже

введите описание изображения здесь

Если вы хотите отключить проверку ограничений, то когда мастер попросит вас сохранить пакет, сохраните его, а затем отредактируйте диспетчер соединений, как показано ниже:

введите описание изображения здесь

Примечание: вы не можете TRUNCATE таблицы, когда определены внешние ключи.

Кин Шах
источник
3

Не отбрасывайте ограничения.

Вам нужно сохранить пакет служб SSIS, созданный мастером, а затем отредактировать его в BIDS / SSDT. Когда вы редактируете пакет, вы сможете контролировать порядок обработки таблиц, чтобы вы могли обрабатывать родительские таблицы, а затем обрабатывать дочерние таблицы, когда все родительские таблицы готовы.

mrdenny
источник
3
Это тоже не очень эффективно, сейчас потребуется почти час, чтобы изменить пакет, чтобы убедиться, что все в правильном порядке, и даже тогда я не уверен. Это будет более громоздким по мере роста БД и делать это каждый раз, нет, спасибо. Там должен быть простой способ сделать это.
1

Подобные проблемы показывают, что люди, которые делают SQL-сервер, никогда не использовали свой продукт. Это такое явное упущение, что нужно задаться вопросом, что еще они просто забыли сделать правильно (у меня есть список из примерно 30 других сводящих с ума проблем, подобных этой, которые мне пришлось преодолеть, чтобы заставить эту работу работать, как это делают другие БД из коробки, в том числе тот факт, что нам нужен паршивый мастер, чтобы сделать это в первую очередь [если бы у меня было время, которое я потратил, ожидая, пока этот мастер подключит и перечислит одни и те же таблицы для одной и той же БД, каждый раз, назад ... у меня будет время для приятного отдыха]).

Я очень ленивый и не хочу печатать EXEC sp_msforeachtable ...дважды каждый раз, когда я делаю это. Моя работа заключалась в том, чтобы оставить ограничения на рабочем сервере и удалить их с сервера разработки. Это предотвратит ошибку, но у этого метода есть несколько ОЧЕНЬ БОЛЬШИХ побочных эффектов. Во-первых, вы больше не сможете просто восстановить полную резервную копию на своем сервере разработки (если вы не согласны с их повторным удалением). Во-вторых, это работает лучше всего, когда вы уверены, что потребители ваших данных также применяют эти ограничения (или не заботятся о них). В моем случае у нас есть только один потребитель (наш веб-сайт), поэтому мы встраивали эти ограничения и в код сайта (т.е. перед удалением записи пользователя мы сначала удаляем все записи телефона для этого пользователя). Да, это, по сути, сводит на нет необходимость в ограничениях в первую очередь и удваивает работу, которую мне нужно сделать, но также дает мне возможность убедиться, что мой код работает с ограничениями на основе СУБД или без них (факт заключается в том, что они все еще находятся в процессе разработки). сервер только в качестве плана на случай непредвиденных обстоятельств). Вы могли бы назвать это недостатком в моем дизайне, но я бы предпочел назвать это обходным путем для некорректной СУБД. Во всяком случае, это все же быстрее и проще сделать это где-либо еще, чем в MSSQL, потому что он не может справиться со своим собственным дизайном.

krowe2
источник
0

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

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

Не точный ответ, но он будет обрабатываться быстро.

user2404431
источник
Спасибо, но я специально сказал, что не хочу писать сценарий ограничения удаления / создания.
0

Просто прочитайте эту тему. Это старый пост, но вот что я сделал, чтобы помочь будущим людям читать это.

В моем случае я хотел импортировать в пустую идентичную таблицу. При редактировании отображения я выбираю <ignore>первичный ключ. Весь мой контент добавляется автоматически.

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

Greg
источник
1
Игнорировать первичный ключ поможет с внешними ключами?
Дезсо
В моем случае да, так как я на самом деле дублировал таблицу. Поэтому я закончил с теми же первичными ключами. Таким образом, внешние ключи, указывающие на мою таблицу, все еще соответствуют правильной записи
Грег