Обмеження зовнішнього ключа SRO DROP TABLE


154

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

GO
IF OBJECT_ID('dbo.[Course]','U') IS NOT NULL
    DROP TABLE dbo.[Course]
GO
IF OBJECT_ID('dbo.[Student]','U') IS NOT NULL
    DROP TABLE dbo.[Student]


2
Перевірте цей відповідь, він допоміг мені;) stackoverflow.com/a/5488670/2205144
xatz

Відповіді:


335

Ні, це не скине вашу таблицю, якщо дійсно є зовнішні ключі, на які вона посилається.

Щоб отримати всі зовнішні ключові зв’язки, що посилаються на вашу таблицю, ви можете використовувати цей SQL (якщо ви перебуваєте на SQL Server 2005 і вище):

SELECT * 
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')

і якщо є такі, з цим твердженням тут, ви можете створити оператори SQL, щоб фактично скинути ці відносини FK:

SELECT 
    'ALTER TABLE [' +  OBJECT_SCHEMA_NAME(parent_object_id) +
    '].[' + OBJECT_NAME(parent_object_id) + 
    '] DROP CONSTRAINT [' + name + ']'
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')

Примітка: згенерована таблиця містить висловлювання для видалення окремих обмежень для запуску в іншому запиті. У моєму випадку це творило чудеса, оскільки мені потрібно було позбутися непотрібної таблиці (для тестування), зберігаючи решту таблиць, у яких ФК було недоторканим.
Маурісіо Кінтана

1
Мені довелося використовувати parent_object_id замість referenced_object_id
Том Робінсон

2
Альтернативою оператору SELECT для отримання всіх таблиць посилань є: EXEC sp_fkeys 'Student';
Buggieboy

невелике коригування цього запиту SELECT 'ALTER TABLE' + OBJECT_SCHEMA_NAME (parent_object_id) + '. [' + OBJECT_NAME (parent_object_id) + '] DROP CONSTRAINT [name]' FROM sys.foreign_keys WHERE referenced_object_id = object_id ('Студент') замінити [ім'я] з назвою
CONSTRAINT

1
Як призначити останній вибір як змінну та виконати його?
Хрвое Т

44

У SQL Server Management Studio 2008 (R2) та новіших версіях ви можете натиснути правою кнопкою миші на

БД -> Завдання -> Створення скриптів

  • Виберіть таблиці, які ви хочете знищити.

  • Виберіть "Зберегти у новому вікні запиту".

  • Натисніть кнопку Додатково.

  • Встановіть сценарій DROP та CREATE на DROP для сценарію.

  • Встановити Іноземні клавіші сценарію на "True".

  • Натисніть кнопку ОК.

  • Клацніть Далі -> Далі -> Готово.

  • Перегляньте сценарій, а потім Виконати.


12
все одно той самий "Не вдалося скинути об'єкт" my_table ", оскільки на нього посилається обмеження FOREIGN KEY.
FrenkyB

6
Як ця відповідь має 28 + рейтинг поза мною ... все ще не працює товариш
AltF4_

1
Хоча він генерує скрипт - цей скрипт не вирішує проблему, на яку випадає таблиця, на яку посилаються обмеження іноземного ключа.
Олексій Шевельов

Працювало як шарм для мене.
Йоган

21

Якщо ви спустите таблицю "дочірня" спочатку, також буде видалений зовнішній ключ. Якщо ви спробуєте спустити таблицю "батьків" спочатку, ви отримаєте "Не вдалося викинути об'єкт" a ", оскільки на нього посилається обмеження FOREIGN KEY." помилка.


2
Правда, але рішення немає. У дитини можуть бути сторонні ключі до інших таблиць та / або, можливо, ви не хочете її кидати в першу чергу.
MaR

4
Правда, і рішення, якщо мета полягає в тому, як зазначено: "Якщо я хочу видалити всі таблиці з моєї бази даних ..."
Філіп Келлі

4
це набагато краща відповідь, ніж прийнята, враховуючи, що
запитуючий

17

Ось ще один спосіб правильно скинути всі таблиці, використовуючи sp_MSdropconstraintsпроцедуру. Найкоротший код, про який я міг придумати:

exec sp_MSforeachtable "declare @name nvarchar(max); set @name = parsename('?', 1); exec sp_MSdropconstraints @name";
exec sp_MSforeachtable "drop table ?";

Чудовий чоловік ............
edCoder


2

Трохи більш загальна версія публікації @mark_s - це мені допомогло

SELECT 
'ALTER TABLE ' +  OBJECT_SCHEMA_NAME(k.parent_object_id) +
'.[' + OBJECT_NAME(k.parent_object_id) + 
'] DROP CONSTRAINT ' + k.name
FROM sys.foreign_keys k
WHERE referenced_object_id = object_id('your table')

просто підключіть назву таблиці та виконайте її результат.


1
Привіт, я намагався скинути свої обмеження на зовнішній ключ вищезазначеним, але коли я йду потім опускати таблицю, він постійно говорить: "Не вдалося відкинути об'єкт, оскільки на нього все ще посилається обмеження зовнішнього ключа ... будь-які ідеї? Дякую заздалегідь
daniness

1

Ось ще один спосіб видалити всі обмеження, за якими слідують самі таблиці, використовуючи фокус конкатенації, FOR XML PATH('')який дозволяє об'єднати кілька вхідних рядків в один вихідний рядок. Потрібно працювати над чим-небудь SQL 2005 та новішими.

Я залишив команди EXECUTE, коментовані для безпеки.

DECLARE @SQL NVARCHAR(max)
;WITH fkeys AS (
    SELECT quotename(s.name) + '.' + quotename(o.name) tablename, quotename(fk.name) constraintname 
    FROM sys.foreign_keys fk
    JOIN sys.objects o ON fk.parent_object_id = o.object_id
    JOIN sys.schemas s ON o.schema_id = s.schema_id
)
SELECT @SQL = STUFF((SELECT '; ALTER TABLE ' + tablename + ' DROP CONSTRAINT ' + constraintname
FROM fkeys
FOR XML PATH('')),1,2,'')

-- EXECUTE(@sql)

SELECT @SQL = STUFF((SELECT '; DROP TABLE ' + quotename(TABLE_SCHEMA) + '.' + quotename(TABLE_NAME) 
FROM INFORMATION_SCHEMA.TABLES 
FOR XML PATH('')),1,2,'')

-- EXECUTE(@sql)

Це не працює добре, тому що не всі FK будуть відкинуті (лише ті, де наші таблиці використовуються як батьківські, де ми повинні скинути також обмеження, де наша таблиця використовувалася як "посилання").
Роман Покровський

Романе, оригінальна публікація стосується видалення зовнішніх ключових обмежень. Моя відповідь не має на меті охоплювати нічого, що перевищує це.
Воррен Румак

1

Ось повний сценарій для реалізації рішення:

create Procedure [dev].DeleteTablesFromSchema
(
    @schemaName varchar(500)
)
As 
begin
    declare @constraintSchemaName nvarchar(128), @constraintTableName nvarchar(128),  @constraintName nvarchar(128)
    declare @sql nvarchar(max)
    -- delete FK first
    declare cur1 cursor for
    select distinct 
    CASE WHEN t2.[object_id] is NOT NULL  THEN  s2.name ELSE s.name END as SchemaName,
    CASE WHEN t2.[object_id] is NOT NULL  THEN  t2.name ELSE t.name END as TableName,
    CASE WHEN t2.[object_id] is NOT NULL  THEN  OBJECT_NAME(d2.constraint_object_id) ELSE OBJECT_NAME(d.constraint_object_id) END as ConstraintName
    from sys.objects t 
        inner join sys.schemas s 
            on t.[schema_id] = s.[schema_id]
        left join sys.foreign_key_columns d 
            on  d.parent_object_id = t.[object_id]
        left join sys.foreign_key_columns d2 
            on  d2.referenced_object_id = t.[object_id]
        inner join sys.objects t2 
            on  d2.parent_object_id = t2.[object_id]
        inner join sys.schemas s2 
            on  t2.[schema_id] = s2.[schema_id]
    WHERE t.[type]='U' 
        AND t2.[type]='U'
        AND t.is_ms_shipped = 0 
        AND t2.is_ms_shipped = 0 
        AND s.Name=@schemaName
    open cur1
    fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
    while @@fetch_status = 0
    BEGIN
        set @sql ='ALTER TABLE ' + @constraintSchemaName + '.' + @constraintTableName+' DROP CONSTRAINT '+@constraintName+';'
        exec(@sql)
        fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
    END
    close cur1
    deallocate cur1

    DECLARE @tableName nvarchar(128)
    declare cur2 cursor for
    select s.Name, p.Name
    from sys.objects p
        INNER JOIN sys.schemas s ON p.[schema_id] = s.[schema_id]
    WHERE p.[type]='U' and is_ms_shipped = 0 
    AND s.Name=@schemaName
    ORDER BY s.Name, p.Name
    open cur2

    fetch next from cur2 into @schemaName,@tableName
    while @@fetch_status = 0
    begin
        set @sql ='DROP TABLE ' + @schemaName + '.' + @tableName
        exec(@sql)
        fetch next from cur2 into @schemaName,@tableName
    end

    close cur2
    deallocate cur2

end
go

1
Removing Referenced FOREIGN KEY Constraints
Assuming there is a parent and child table Relationship in SQL Server:

--First find the name of the Foreign Key Constraint:
  SELECT * 
  FROM sys.foreign_keys
  WHERE referenced_object_id = object_id('States')

--Then Find foreign keys referencing to dbo.Parent(States) table:
   SELECT name AS 'Foreign Key Constraint Name', 
           OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id) AS 'Child Table'
   FROM sys.foreign_keys 
   WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND 
              OBJECT_NAME(referenced_object_id) = 'dbo.State'

 -- Drop the foreign key constraint by its name 
   ALTER TABLE dbo.cities DROP CONSTRAINT FK__cities__state__6442E2C9;

 -- You can also use the following T-SQL script to automatically find 
 --and drop all foreign key constraints referencing to the specified parent 
 -- table:

 BEGIN

DECLARE @stmt VARCHAR(300);

-- Cursor to generate ALTER TABLE DROP CONSTRAINT statements  
 DECLARE cur CURSOR FOR
 SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.' + 
 OBJECT_NAME(parent_object_id) +
                ' DROP CONSTRAINT ' + name
 FROM sys.foreign_keys 
 WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND 
            OBJECT_NAME(referenced_object_id) = 'states';

 OPEN cur;
 FETCH cur INTO @stmt;

 -- Drop each found foreign key constraint 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    EXEC (@stmt);
    FETCH cur INTO @stmt;
  END

  CLOSE cur;
  DEALLOCATE cur;

  END
  GO

--Now you can drop the parent table:

 DROP TABLE states;
--# Command(s) completed successfully.

0

Використовуючи диспетчер SQL Server, ви можете скасувати обмеження зовнішніх ключів з інтерфейсу користувача. Якщо ви хочете видалити таблицю, Diaryале у таблиці користувача є зовнішній ключ, що DiaryIdвказує на Diaryтаблицю, ви можете розгорнути (за допомогою символу плюс) Userтаблицю, а потім розгорнути Foreign Keysрозділ. Клацніть правою кнопкою миші зовнішній ключ, який вказує на таблицю щоденника, а потім виберіть Delete. Потім можна розгорнути Columnsрозділ, клацнути правою кнопкою миші та також видалити стовпець DiaryId. Тоді ви можете просто запустити:

drop table Diary

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


0

Якщо ви перебуваєте на сервері mysql і якщо ви не проти втратити свої таблиці, ви можете скористатися простим запитом, щоб видалити кілька таблиць одночасно:

SET foreign_key_checks = 0;
DROP TABLE IF EXISTS table_a,table_b,table_c,table_etc;
SET foreign_key_checks = 1;

Таким чином, не має значення в якому порядку ви використовуєте таблицю для запиту.

Якщо хтось скаже щось про те, що це не гарне рішення, якщо у вас база даних з багатьма таблицями: я згоден!


Я отримуюIncorrect syntax near '='. (102) (SQLExecDirectW)
Метт

@Matt Bit важко здогадатися, при якому '=' ви отримуєте цю помилку.
Els den Iep

3
foreign_key_checksне працюватиме на сервері MSSQL. Я думаю, що це специфічна змінна MySql.
ooXei1sh

1
@ ooXei1sh Ні, не на MSSQL. Ось чому я кажу на початку своєї публікації: "Якщо ви перебуваєте на сервері MYSQL".
Els den Iep

0

виконайте наведений нижче код, щоб отримати ім'я обмеження іноземного ключа, яке блокує вашу краплю. Наприклад, я беру rolesстіл.

      SELECT *
      FROM sys.foreign_keys
      WHERE referenced_object_id = object_id('roles');

      SELECT name AS 'Foreign Key Constraint Name',
      OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id)
      AS 'Child Table' FROM sys.foreign_keys
      WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo'
      AND OBJECT_NAME(referenced_object_id) = 'dbo.roles'

ви отримаєте назву FK як-небудь нижче: FK__Table1__roleId__1X1H55C1

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

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Готово!


-4

Якщо я хочу видалити всі таблиці з моєї бази даних

Тоді набагато простіше скинути всю базу даних:

DROP DATABASE WorkerPensions

71
Даючи вам -1 для цього, оскільки це не є коректною відповіддю на питання з двох важливих причин: 1) Це видаляє набагато більше, ніж таблиці! Збережені процедури, функції, UDT, безпека, збірки .NET і т. Д. Всі відходять із DROP DATABASE. 2) Можливо, вам не дозволять створювати бази даних, наприклад, з централізованим керованим середовищем розробників, де бази даних забезпечуються ІТ і мають додаткові вимоги під час створення, про які ви не знаєте.
Воррен Румак

-4

Якщо ви хочете до DROPтаблиці, на яку посилається інша таблиця, використовуючи зовнішній ключ

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Я думаю, що це має працювати для вас.


1
немає cascade constraintsна сервері sql
JackyJohnson
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.