2009-01-27 33 views
175

tôi có thể thả một bảng nếu nó tồn tại bằng cách sử dụng đoạn mã sau nhưng không biết làm thế nào để làm điều tương tự với một hạn chế:Làm thế nào để thả một ràng buộc khoá ngoại nếu nó tồn tại trong máy chủ sql?

IF EXISTS(SELECT 1 FROM sys.objects WHERE OBJECT_ID = OBJECT_ID(N'TableName') AND type = (N'U')) DROP TABLE TableName 
go 

Tôi cũng thêm các hạn chế sử dụng mã này:

ALTER TABLE [dbo].[TableName] 
    WITH CHECK ADD CONSTRAINT [FK_TableName_TableName2] FOREIGN KEY([FK_Name]) 
    REFERENCES [dbo].[TableName2] ([ID]) 
go 

Trả lời

248
IF (OBJECT_ID('FK_TableName_TableName2', 'F') IS NOT NULL) 
BEGIN 
    ALTER TABLE dbo.TableName DROP CONSTRAINT FK_TableName_TableName2 
END 
+1

nếu bit tồn tại của tôi thực sự sau .. xin lỗi. tôi sẽ cập nhật câu hỏi của tôi để nó rõ ràng hơn! – solrevdev

+0

Xin lỗi John đã bỏ lỡ bit đó, tôi sẽ cập nhật câu trả lời của tôi –

+2

Nếu bạn đang sử dụng EF tạo ra các phím nước ngoài có dấu chấm trong tên bạn cần đặt dấu ngoặc ôm xung quanh các tên như [dbo]. [FK_dbo.MyTable_Etc] –

7
ALTER TABLE [dbo].[TableName] 
    DROP CONSTRAINT FK_TableName_TableName2 
+2

Có thể đặt trong khối 'TRY..CATCH'. – onedaywhen

+0

"... nếu nó tồn tại trong máy chủ sql? ..." - làm thế nào để bạn kiểm tra ràng buộc đó tồn tại? – new2ios

13

Câu trả lời của James hoạt động tốt nếu bạn biết tên của ràng buộc thực tế. Điều khó khăn là trong các trường hợp di sản thế giới thực và khác, bạn có thể không biết những gì ràng buộc được gọi.

Nếu đây là trường hợp bạn có nguy cơ tạo ra những hạn chế trùng lặp, để tránh bạn có thể sử dụng:

create function fnGetForeignKeyName 
(
    @ParentTableName nvarchar(255), 
    @ParentColumnName nvarchar(255), 
    @ReferencedTableName nvarchar(255), 
    @ReferencedColumnName nvarchar(255) 
) 
returns nvarchar(255) 
as 
begin 
    declare @name nvarchar(255) 

    select @name = fk.name from sys.foreign_key_columns fc 
    join sys.columns pc on pc.column_id = parent_column_id and parent_object_id = pc.object_id 
    join sys.columns rc on rc.column_id = referenced_column_id and referenced_object_id = rc.object_id 
    join sys.objects po on po.object_id = pc.object_id 
    join sys.objects ro on ro.object_id = rc.object_id 
    join sys.foreign_keys fk on fk.object_id = fc.constraint_object_id 
    where 
     po.object_id = object_id(@ParentTableName) and 
     ro.object_id = object_id(@ReferencedTableName) and 
     pc.name = @ParentColumnName and 
     rc.name = @ReferencedColumnName 

    return @name 
end 

go 

declare @name nvarchar(255) 
declare @sql nvarchar(4000) 
-- hunt for the constraint name on 'Badges.BadgeReasonTypeId' table refs the 'BadgeReasonTypes.Id' 
select @name = dbo.fnGetForeignKeyName('dbo.Badges', 'BadgeReasonTypeId', 'dbo.BadgeReasonTypes', 'Id') 
-- if we find it, the name will not be null 
if @name is not null 
begin 
    set @sql = 'alter table Badges drop constraint ' + replace(@name,']', ']]') 
    exec (@sql) 
end 
3
Declare @FKeyRemoveQuery NVarchar(max) 

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.TableName')) 

BEGIN 
    SELECT @FKeyRemoveQuery='ALTER TABLE dbo.TableName DROP CONSTRAINT [' + LTRIM(RTRIM([name])) + ']' 
    FROM sys.foreign_keys 
    WHERE parent_object_id = OBJECT_ID(N'dbo.TableName') 

    EXECUTE Sp_executesql @FKeyRemoveQuery 

END 
+0

chỉ có thêm điều tôi sẽ thêm là bao gồm tên như một bộ lọc trong lựa chọn từ sys.foreign_keys vì có thể có nhiều phím nước ngoài trên bàn – Koenyn

13
IF (OBJECT_ID('DF_Constraint') IS NOT NULL) 
BEGIN 
    ALTER TABLE [dbo].[tableName] 
    DROP CONSTRAINT DF_Constraint 
END 
231

Đây là đơn giản hơn rất nhiều so với các giải pháp đề xuất hiện:

IF (OBJECT_ID('dbo.FK_ConstraintName', 'F') IS NOT NULL) 
BEGIN 
    ALTER TABLE dbo.TableName DROP CONSTRAINT FK_ConstraintName 
END 

Nếu bạn cần loại bỏ ràng buộc khác, đây là các mã áp dụng để chuyển vào hàm OBJECT_ID() trong tham số thứ hai vị trí eter:

C = CHECK constraint 
D = DEFAULT (constraint or stand-alone) 
F = FOREIGN KEY constraint 
PK = PRIMARY KEY constraint 
UQ = UNIQUE constraint 

Bạn cũng có thể sử dụng OBJECT_ID mà không có tham số thứ hai.

Full Danh sách các loại here:

kiểu Object:

AF = Aggregate function (CLR) 
C = CHECK constraint 
D = DEFAULT (constraint or stand-alone) 
F = FOREIGN KEY constraint 
FN = SQL scalar function 
FS = Assembly (CLR) scalar-function 
FT = Assembly (CLR) table-valued function 
IF = SQL inline table-valued function 
IT = Internal table 
P = SQL Stored Procedure 
PC = Assembly (CLR) stored-procedure 
PG = Plan guide 
PK = PRIMARY KEY constraint 
R = Rule (old-style, stand-alone) 
RF = Replication-filter-procedure 
S = System base table 
SN = Synonym 
SO = Sequence object 

Áp dụng cho: SQL Server 2012 thông qua SQL Server 2014.

SQ = Service queue 
TA = Assembly (CLR) DML trigger 
TF = SQL table-valued-function 
TR = SQL DML trigger 
TT = Table type 
U = Table (user-defined) 
UQ = UNIQUE constraint 
V = View 
X = Extended stored procedure 
+1

+1 Vì vậy, dễ dàng hơn nhiều để đọc và duy trì. – Askolein

+0

+1 Giúp tôi bỏ ràng buộc 'DF' của tôi (sử dụng 'D'). –

+0

Danh sách đầy đủ các loại [tại đây] (http://technet.microsoft.com/en-us/library/ms190324.aspx) (nghĩa là, công cụ này hoạt động cho [tất cả các loại công cụ] (http://stackoverflow.com)/a/7887033/1028230), không chỉ các phím). – ruffin

1

Tôi nghĩ rằng điều này sẽ hữu ích cho bạn ...

DECLARE @ConstraintName nvarchar(200) 
SELECT 
    @ConstraintName = KCU.CONSTRAINT_NAME 
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC 
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU 
    ON KCU.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG 
    AND KCU.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA 
    AND KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME 
WHERE 
    KCU.TABLE_NAME = 'TABLE_NAME' AND 
    KCU.COLUMN_NAME = 'TABLE_COLUMN_NAME' 
IF @ConstraintName IS NOT NULL EXEC('alter table TABLE_NAME drop CONSTRAINT ' + @ConstraintName) 

Nó sẽ xóa ràng buộc khoá ngoại dựa trên bảng và cột cụ thể.

0

Bạn có thể sử dụng các truy vấn đó để tìm tất cả FK cho bảng của mình.

Declare @SchemaName VarChar(200) = 'Schema Name' 
Declare @TableName VarChar(200) = 'Table name' 

-- Find FK in This table. 
SELECT 
    'IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N''' + 
     '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']' 
     + ''') AND parent_object_id = OBJECT_ID(N''' + 
     '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' 
     + OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' + 

    'ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + 
    '.[' + OBJECT_NAME(FK.parent_object_id) + 
    '] DROP CONSTRAINT ' + FK.name 
    , S.name , O.name, OBJECT_NAME(FK.parent_object_id) 
FROM sys.foreign_keys AS FK 
INNER JOIN Sys.objects As O 
    ON (O.object_id = FK.parent_object_id) 
INNER JOIN SYS.schemas AS S 
    ON (O.schema_id = S.schema_id) 
WHERE 
     O.name = @TableName 
     And S.name = @SchemaName 


-- Find the FKs in the tables in which this table is used 
    SELECT 
    ' IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N''' + 
     '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']' 
     + ''') AND parent_object_id = OBJECT_ID(N''' + 
     '[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' 
     + OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' + 

    ' ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + 
    '.[' + OBJECT_NAME(FK.parent_object_id) + 
    '] DROP CONSTRAINT ' + FK.name 
    , S.name , O.name, OBJECT_NAME(FK.parent_object_id) 
FROM sys.foreign_keys AS FK 
INNER JOIN Sys.objects As O 
    ON (O.object_id = FK.referenced_object_id) 
INNER JOIN SYS.schemas AS S 
    ON (O.schema_id = S.schema_id) 
WHERE 
     O.name = @TableName 
     And S.name = @SchemaName 
0

Câu trả lời được chấp nhận về câu hỏi này dường như không làm việc cho tôi.Tôi đã đạt được điều tương tự với một phương pháp hơi khác:

IF (select object_id from sys.foreign_keys where [name] = 'FK_TableName_TableName2') IS NOT NULL 
BEGIN 
    ALTER TABLE dbo.TableName DROP CONSTRAINT FK_TableName_TableName2 
END 
Các vấn đề liên quan