SQL DROP ข้อ จำกัด คีย์ต่างประเทศของตาราง


154

ถ้าฉันต้องการลบตารางทั้งหมดในฐานข้อมูลของฉันเช่นนี้มันจะดูแลข้อ จำกัด foreign key หรือไม่? ถ้าไม่ฉันจะดูแลก่อนได้อย่างไร

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

หมายเหตุ: ตารางที่สร้างขึ้นมีคำสั่งเพื่อลบข้อ จำกัด แต่ละข้อที่จะเรียกใช้ในคิวรีอื่น มันทำงานได้อย่างมหัศจรรย์ในกรณีของฉันเนื่องจากฉันต้องการกำจัดตารางที่ไร้ประโยชน์ (เพื่อจุดประสงค์ในการทดสอบ) ในขณะที่รักษาตารางที่เหลือซึ่งมี FK ไว้ให้เหมือนเดิม
Mauricio Quintana

1
ฉันต้องใช้ parent_object_id แทนที่จะเป็น referenced_object_id
Tom Robinson

2
อีกทางเลือกหนึ่งของคำสั่ง SELECT เพื่อรับตารางอ้างอิงทั้งหมดคือ: EXEC sp_fkeys 'Student';
Buggieboy

การปรับแต่งแบบสอบถามนี้ให้เลือก 'ALTER TABLE' + OBJECT_SCHEMA_NAME (parent_object_id) + '[' + OBJECT_NAME (parent_object_id) + '] DROP CONSTRAINT [ชื่อ]' จาก sys.foreign_keys ซึ่งมีการอ้างอิงเล็กน้อย ด้วยชื่อ CONSTRAINT
Stas Svishov

1
วิธีการกำหนดตัวเลือกสุดท้ายของคุณเป็นตัวแปรและดำเนินการได้อย่างไร
Hrvoje T

44

ใน SQL Server Management Studio 2008 (R2) และใหม่กว่าคุณสามารถคลิกขวาที่

DB -> Tasks -> สร้างสคริปต์

  • เลือกตารางที่คุณต้องการ DROP

  • เลือก "บันทึกไปยังหน้าต่างแบบสอบถามใหม่"

  • คลิกที่ปุ่มขั้นสูง

  • ตั้งค่า Script DROP และสร้างเป็น Script DROP

  • ตั้งค่า Foreign Key ของสคริปต์เป็น True

  • คลิกตกลง

  • คลิกถัดไป -> ถัดไป -> เสร็จสิ้น

  • ดูสคริปต์แล้วดำเนินการ


12
ยังคงเหมือนเดิม 'ไม่สามารถวางวัตถุ' my_table 'ได้เนื่องจากมีการอ้างอิงโดยข้อ จำกัด ของคีย์ต่างประเทศ
FrenkyB

6
คำตอบนี้มีคะแนนมากกว่า 28 คะแนนอย่างไร ... ยังไม่สามารถใช้งานได้
AltF4_

1
ในขณะที่มันสร้างสคริปต์ - สคริปต์นั้นไม่สามารถแก้ปัญหาได้ซึ่งวางตารางที่อ้างถึงโดยข้อ จำกัด Foreign Key
Alexey Shevelyov

ทำงานเหมือนเสน่ห์สำหรับฉัน
Johan

21

หากคุณวางตาราง "ลูก" ไว้ก่อนรหัสต่างประเทศก็จะลดลงเช่นกัน หากคุณพยายามที่จะวางตาราง "ผู้ปกครอง" ก่อนคุณจะได้รับ "ไม่สามารถวางวัตถุ 'a' เพราะมันถูกอ้างอิงโดยข้อ จำกัด ที่สำคัญของต่างประเทศ ความผิดพลาด


2
จริง แต่ไม่มีวิธีแก้ เด็กสามารถมีคีย์ต่างประเทศเพื่อตาราง oher และ / หรือคุณอาจไม่ต้องการวางในครั้งแรก
มี.ค.

4
True และวิธีการแก้ปัญหาถ้าเป้าหมายคือตามที่ระบุไว้ว่า "ถ้าฉันต้องการลบตารางทั้งหมดในฐานข้อมูลของฉัน ..."
ฟิลิปเคลลี่

4
นี่เป็นคำตอบที่ดีกว่าคำตอบที่ผู้ตอบคำถามต้องการ "ลบตารางทั้งหมดในฐานข้อมูลของฉัน"
lukkea

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

หากเป็น SQL Server คุณจะต้องวางข้อ จำกัด ก่อนจึงจะสามารถวางตารางได้


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
สวัสดีฉันพยายามวางข้อ จำกัด กุญแจต่างประเทศของฉันไว้ด้านบน แต่เมื่อฉันไปวางตารางหลังจากนั้นมันก็พูดว่า "ไม่สามารถวางวัตถุได้เนื่องจากยังมีการอ้างถึงโดยข้อ จำกัด Foreign Key ... ความคิดใด ๆ ขอบคุณล่วงหน้า?.
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 จะไม่ถูกลบทั้งหมด (เฉพาะที่ที่ตารางของเราถูกใช้เป็นผู้ปกครองซึ่งเราควรจะวางข้อ จำกัด ที่ตารางของเราถูกใช้เป็น "อ้างอิง")
Roman Pokrovskij

โรมันโพสต์ดั้งเดิมนั้นเกี่ยวกับการลบข้อ จำกัด กุญแจต่างประเทศ คำตอบของฉันไม่ได้ตั้งเป้าหมายที่จะครอบคลุมอะไรนอกจากนั้น
Warren Rumak

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 Manager คุณสามารถลบข้อ จำกัด กุญแจต่างประเทศจาก UI หากคุณต้องการลบตาราง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 2) คุณอาจไม่ได้รับอนุญาตให้สร้างฐานข้อมูลเช่นสภาพแวดล้อม dev ที่จัดการจากส่วนกลางซึ่งฐานข้อมูลถูกจัดเตรียมโดย IT และมีข้อกำหนดเพิ่มเติม ณ เวลาที่คุณไม่ทราบ
Warren Rumak

-4

หากคุณต้องการDROPตารางที่อ้างอิงโดยตารางอื่นโดยใช้การใช้งาน Foreign Key

DROP TABLE *table_name* CASCADE CONSTRAINTS;
ฉันคิดว่ามันควรจะเหมาะกับคุณ


1
ไม่มีcascade constraintsในเซิร์ฟเวอร์ sql
JackyJohnson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.