Як мені боротися з обмеженнями FK під час імпорту даних за допомогою майстра імпорту / експорту DTS?


16

Я намагаюся використовувати майстра імпорту та експорту SQL Server, щоб скопіювати дані з мого виробничого db до мого dev db, але коли я це роблю, не вдається помилка "Стан 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'

За допомогою цього методу мені вдалося імпортувати всі дані без проблем.


1
sp_msforeachtablesp_MSForEachDb) є недокументованим і не підтримується. Не слід / уникати його використання. Це може пропустити таблиці !! Дивіться цю публікацію від @AaronBertrand -> sqlblog.com/blogs/aaron_bertrand/archive/2010/12/29/… та цей елемент підключення - (MS вказує, що вони не зможуть її виправити) -> connect.microsoft.com/SQLServer / відгуки / деталі / 264677 /…
Кін Шах

Я працював ідеально для мене після години вибиття мозку, намагаючись обійти обмеження ФК щодо експорту даних.
levininja

Запускаючи Azure SQL V12, я отримую помилку "Не вдалося знайти збережену процедуру 'sp_msforeachtable'."
Дай


Ви людина, яка
Може

5

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

Я чмокав , але ось що я зробив:

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

  2. Якщо під час створення будь-які дані були автоматично вставлені у вашDB , запустіть a DELETE FROM YourDB.dbo.tblYourTable.

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

  4. Клацніть правою кнопкою миші на вашDB в 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. Повторіть ad infinitum.
  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/…
Санчітос

4

У майстрі імпорту ви можете спочатку видалити рядки, і якщо у вас є поля ідентичності, ви можете ввімкнути вставку особи, як показано нижче

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

Якщо ви хочете відключити обмеження перевірки, тоді, коли майстер попросить вас зберегти пакунок, збережіть його, а потім відредагуйте менеджер з'єднань, як показано нижче:

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

Примітка. Ви не можете TRUNCATE таблиці, якщо визначені іноземні клавіші.


3

Не скидайте обмежень.

Що вам слід зробити, це зберегти пакет SSIS, який створює майстер, а потім відредагувати його в BIDS / SSDT. Під час редагування пакету ви зможете контролювати порядок обробки таблиць, щоб ви могли обробити батьківські таблиці, а потім обробити дочірні таблиці, коли всі батьківські таблиці виконані.


3
Це теж не дуже ефективно, зараз буде потрібно майже годину, щоб змінити пакет, щоб переконатися, що все в правильному порядку, і навіть тоді я не можу бути впевнений. Це зробить більшу громіздкість у міру зростання БД і робити це кожного разу, не дякую. Має бути простий спосіб зробити це.

1

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

Я дуже лінивий і не хочу вводити текст EXEC sp_msforeachtable ...двічі кожен раз, коли я роблю це. Моя робота полягала в тому, щоб залишити обмеження на виробничому сервері та видалити їх із сервера розробників. Це дозволить уникнути помилки, але цей метод має кілька ДУЖЕ ВЕЛИЧИХ побічних ефектів. По-перше, ви більше не зможете просто відновити повну резервну копію на сервері розробників (якщо тільки ви все не будете готові знову видалити їх). По-друге, це найкраще працює, коли ви впевнені, що споживачі ваших даних також застосовують ці обмеження (або не піклуються про них). У моєму випадку у нас є лише один споживач (наш веб-сайт), тому ми також вбудували ці обмеження в код сайту (тобто перед тим, як видалити запис користувача, спочатку видалимо всі записи телефону для цього користувача). так, це, по суті, заперечує необхідність обмежень в першу чергу і подвоює роботу, яку мені потрібно виконати, але це також дає мені можливість переконатися, що мій код працює з обмеженнями на базі СУБД (справа в тому, що вони все ще знаходяться на виробництві сервер лише як план дій у надзвичайних ситуаціях). Ви можете назвати це недоліком у моїй конструкції, але я вважаю за краще це вирішення несправних СУБД. У будь-якому випадку, це все-таки швидше і простіше зробити це деінде, ніж зсередини MSSQL, оскільки він не в змозі впоратися з власним дизайном.


0

Я думаю, ви не можете виконати резервне копіювання та відновлення з виробничого сервера, оскільки це важливі дані. Ну а без належних прав це дійсно стає складнішим. Але якщо у вас є правильне резервне копіювання n db, ви можете виконати це.

Інакше, один із способів, який я рекомендував би, - це скинути всі ваші обмеження та індекси, а потім знову додати їх, коли дані будуть імпортовані чи експортовані.

Не точна відповідь, але вона буде оброблена швидко.


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

0

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

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

Сподіваюся, це комусь допоможе


1
Ігнорування первинного ключа допоможе із зовнішніми ключами?
дезсо

У моєму випадку так, оскільки я насправді копіював таблицю. Тож я закінчив тими ж первинними ключами. Тож зовнішні ключі, що вказують на мій стіл, досі відповідають правильному запису
Грег,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.