SQL DROP BẢNG ràng buộc khóa ngoài


154

Nếu tôi muốn xóa tất cả các bảng trong cơ sở dữ liệu của mình như thế này, nó có xử lý các ràng buộc khóa ngoại không? Nếu không, làm thế nào để tôi chăm sóc điều đó đầu tiên?

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
Kiểm tra câu trả lời này, nó đã giúp tôi;) stackoverflow.com/a/5488670/2205144
xatz

Câu trả lời:


335

Không, điều này sẽ không làm rơi bàn của bạn nếu thực sự có khóa ngoại tham chiếu đến nó.

Để có được tất cả các mối quan hệ khóa ngoài tham chiếu bảng của bạn, bạn có thể sử dụng SQL này (nếu bạn đang sử dụng SQL Server 2005 trở lên):

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

và nếu có bất kỳ, với câu lệnh này ở đây, bạn có thể tạo các câu lệnh SQL để thực sự loại bỏ các mối quan hệ 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')

Lưu ý: bảng được tạo chứa các câu lệnh để xóa các ràng buộc riêng lẻ được chạy trong một truy vấn khác. Nó đã làm việc kỳ diệu trong trường hợp của tôi vì tôi cần phải loại bỏ một bảng vô dụng (cho mục đích thử nghiệm) trong khi vẫn duy trì các bảng còn lại có FK còn nguyên vẹn.
Mauricio Quintana

1
Tôi đã phải sử dụng Parent_object_id thay vì tham chiếu_object_id
Tom Robinson

2
Một thay thế cho câu lệnh CHỌN để nhận tất cả các bảng tham chiếu là: EXEC sp_fkeys 'Student';
Buggieboy

điều chỉnh nhỏ truy vấn này CHỌN 'ALTER TABLE' + OBJECT_SCHema_NAME (Parent_object_id) + '. [' + OBJECT_NAME (Parent_object_id) + '] DROP CONSTRAINT [name]' TỪ sys.forign_keys WHERE tham chiếu_object_id với tên CONSTRAINT
Stas Svishov

1
Làm thế nào để chỉ định lựa chọn cuối cùng của bạn như là một biến và thực hiện nó?
Hrvoje T

44

Trong SQL Server Management Studio 2008 (R2) và mới hơn, bạn có thể Nhấp chuột phải vào

DB -> Nhiệm vụ -> Tạo tập lệnh

  • Chọn các bảng bạn muốn DROP.

  • Chọn "Lưu vào cửa sổ truy vấn mới".

  • Nhấp vào nút Nâng cao.

  • Đặt Script DROP và CREATE thành Script DROP.

  • Đặt Script Khóa ngoài thành True.

  • Nhấn OK.

  • Nhấp vào Tiếp theo -> Tiếp theo -> Kết thúc.

  • Xem kịch bản và sau đó Thực thi.


12
vẫn như vậy 'Không thể thả đối tượng' my_table 'vì nó được tham chiếu bởi một ràng buộc FOREIGN KEY.
FrenkyB

6
Làm thế nào câu trả lời này có xếp hạng
28+

1
Mặc dù nó tạo ra tập lệnh - tập lệnh đó không giải quyết được vấn đề, đó là việc bỏ bảng được tham chiếu bởi các ràng buộc của Khóa ngoài.
Alexey Shevelyov

Làm việc như một cơ duyên đối với tôi.
Johan

21

Nếu bạn bỏ bảng "con" trước, khóa ngoại cũng sẽ bị hủy. Nếu bạn cố gắng bỏ bảng "cha mẹ" trước, bạn sẽ nhận được "Không thể thả đối tượng 'a' vì nó được tham chiếu bởi ràng buộc FOREIGN KEY." lỗi.


2
Đúng, nhưng không có giải pháp. Trẻ có thể có các khóa ngoại cho các bảng oher và / hoặc bạn có thể không muốn thả nó ở vị trí đầu tiên.
MaR

4
Đúng và là một giải pháp nếu mục tiêu là, như đã nêu, "Nếu tôi muốn xóa tất cả các bảng trong cơ sở dữ liệu của mình ..."
Philip Kelley

4
đây là một câu trả lời tốt hơn nhiều so với câu trả lời được chấp nhận, cho rằng người hỏi muốn "xóa tất cả các bảng trong cơ sở dữ liệu của tôi"
lukkea

17

Đây là một cách khác để loại bỏ tất cả các bảng một cách chính xác, sử dụng sp_MSdropconstraintsthủ tục. Mã ngắn nhất tôi có thể nghĩ ra:

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

Người đàn ông tuyệt vời ............
edCoder

2

Nếu đó là SQL Server, bạn phải loại bỏ ràng buộc trước khi bạn có thể bỏ bảng.


2

Phiên bản chung chung hơn của những gì @mark_s đã đăng, điều này đã giúp tôi

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')

chỉ cần cắm tên bảng của bạn và thực hiện kết quả của nó.


1
Xin chào, tôi đã cố gắng loại bỏ các ràng buộc khóa ngoại của mình ở trên, nhưng khi tôi đi thả một bảng sau đó, nó vẫn báo "Không thể bỏ đối tượng vì nó vẫn bị tham chiếu bởi ràng buộc Khóa ngoài ... Có ý kiến ​​gì không? Cảm ơn trước.
daniness 12/12/17

1

Đây là một cách khác để xóa tất cả các ràng buộc theo sau bởi chính các bảng, sử dụng thủ thuật ghép nối liên quan đến FOR XML PATH('')việc cho phép hợp nhất nhiều hàng đầu vào thành một hàng đầu ra. Nên hoạt động trên mọi thứ SQL 2005 trở lên.

Tôi đã để lại các lệnh EXECUTE nhận xét cho an toàn.

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)

Điều này không hoạt động tốt vì không phải tất cả FK sẽ bị loại bỏ (chỉ những người trong đó các bảng của chúng tôi được sử dụng làm cha mẹ, nơi chúng tôi cũng nên bỏ ràng buộc trong đó bảng của chúng tôi được sử dụng làm "tham chiếu").
La Mã Pokrovskij

Roman, bài viết gốc là về việc xóa các ràng buộc khóa ngoại. Câu trả lời của tôi không nhằm mục đích bao gồm bất cứ điều gì ngoài điều đó.
Warren Rumak

1

Đây là một kịch bản hoàn chỉnh để thực hiện một giải pháp:

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

Sử dụng SQL Server Manager, bạn có thể loại bỏ các ràng buộc khóa ngoài từ UI. Nếu bạn muốn xóa bảng Diarynhưng bảng Người dùng có khóa ngoạiDiaryId trỏ vào Diarybảng, bạn có thể mở rộng (sử dụng ký hiệu cộng) cho Userbảng và sau đó mở rộng Foreign Keysphần. Nhấp chuột phải vào khóa ngoại trỏ vào bảng nhật ký sau đó chọn Delete. Sau đó, bạn có thể mở rộng Columnsphần, nhấp chuột phải và xóa cột DiaryIdquá. Sau đó, bạn có thể chạy:

drop table Diary

Tôi biết câu hỏi thực tế của bạn là về việc xóa tất cả các bảng, vì vậy điều này có thể không hữu ích cho trường hợp đó. Tuy nhiên, nếu bạn chỉ muốn xóa một vài bảng thì điều này hữu ích, tôi tin rằng (tiêu đề không đề cập rõ ràng đến việc xóa tất cả các bảng).


0

Nếu bạn đang ở trên máy chủ mysql và nếu bạn không mất các bảng của mình, bạn có thể sử dụng một truy vấn đơn giản để xóa nhiều bảng cùng một lúc:

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

Theo cách này, việc bạn sử dụng bảng trong truy vấn của bạn theo thứ tự nào không quan trọng.

Nếu bất cứ ai sẽ nói điều gì đó về thực tế rằng đây không phải là một giải pháp tốt nếu bạn có một cơ sở dữ liệu với nhiều bảng: Tôi đồng ý!


Tôi nhận đượcIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt

@Matt Bit khó đoán tại đó '=' bạn gặp lỗi đó.
Els den Iep

3
foreign_key_checkssẽ không hoạt động trên máy chủ MSSQL. Tôi nghĩ đó là một biến số cụ thể của MySql.
ooXei1sh

1
@ ooXei1sh Không không trên MSSQL. Đó là lý do tại sao tôi nói khi bắt đầu bài viết của mình: "Nếu bạn đang ở trên máy chủ MYSQL".
Els den Iep

0

thực thi đoạn mã dưới đây để lấy tên ràng buộc khóa ngoài chặn khối thả của bạn. Ví dụ, tôi lấy cái rolesbàn.

      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'

bạn sẽ nhận được tên FK như sau: FK__Table1__roleId__1X1H55C1

Bây giờ hãy chạy đoạn mã dưới đây để xóa tham chiếu FK nhận được từ phía trên.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Làm xong!


-4

Nếu tôi muốn xóa tất cả các bảng trong cơ sở dữ liệu của tôi

Sau đó, việc bỏ toàn bộ cơ sở dữ liệu sẽ dễ dàng hơn nhiều:

DROP DATABASE WorkerPensions

71
Cho bạn -1 cho điều này vì đây không phải là câu trả lời hợp lệ cho câu hỏi, vì hai lý do quan trọng: 1) Nó xóa nhiều hơn rất nhiều so với bảng! Các thủ tục được lưu trữ, các chức năng, UDT, bảo mật, các cụm .NET, v.v ... đều biến mất với một DROP DATABASE. 2) Bạn không được phép tạo cơ sở dữ liệu, ví dụ môi trường nhà phát triển được quản lý tập trung nơi cơ sở dữ liệu được cung cấp bởi CNTT và có các yêu cầu bổ sung tại thời điểm tạo mà bạn không biết.
Warren Rumak

-4

Nếu bạn muốn DROPmột bảng đã được tham chiếu bởi bảng khác bằng cách sử dụng khóa ngoại

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Tôi nghĩ rằng nó nên làm việc cho bạn.


1
không có cascade constraintsmáy chủ sql
JackyJohnson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.