외래 키 제약 조건이 SQL Server에있는 경우에만 어떻게 삭제합니까?


235

다음 코드를 사용하여 테이블이 존재하는 경우 테이블을 삭제할 수 있지만 제약 조건으로 동일한 작업을 수행하는 방법을 모릅니다.

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

이 코드를 사용하여 제약 조건을 추가합니다.

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

답변:


321

Eric Isaacs의 답변 에서 더 간단한 해결책이 제공됩니다 . 그러나 모든 테이블에서 제약 조건을 찾습니다. 특정 테이블에서 외래 키 제약 조건을 대상으로하려면 다음을 사용하십시오.

IF EXISTS (SELECT * 
  FROM sys.foreign_keys 
   WHERE object_id = OBJECT_ID(N'dbo.FK_TableName_TableName2')
   AND parent_object_id = OBJECT_ID(N'dbo.TableName')
)
  ALTER TABLE [dbo.TableName] DROP CONSTRAINT [FK_TableName_TableName2]

1
그것의 경우 내가 존재하는 비트 정말 후 .. 죄송합니다. 더 명확하게 질문을 업데이트하겠습니다!
solrevdev

2
당신은 이름에 점으로 EF 생성 외래 키를 사용하는 경우는 다음과 같이 이름을 대괄호 둘 필요가 [DBO] [FK_dbo.MyTable_Etc].
데이비드 Sopko

MSSQL 2017에서는 이제 열이 constraint_object_id그냥 호출되는 것 같지 않습니다object_id
codenamezero

1
작동하지 않습니다. 내가 아는 외래 키의 OBJECT_ID ( '[CONSTRAINT_NAME]', 'F')가 존재하며 null을 반환했습니다.
멜버른 개발자

1
@MelbourneDeveloper 외래 키가 dbo가 아닌 스키마에있는 경우 스키마 접두사가 필요할 수 있습니다. 예를 들어, IF (SELECT OBJECT_ID (N '[Schema]. [FK_Name]', N'F '))는 NULL이 아닙니다. 나는 당신과 비슷한 문제가 있었으며 (귀하의 솔루션도 나에게 도움이되었다)이 예제를 통해 작동했다. SQL Server 2012를 실행하고 있습니다.
iokevins

318

이것은 현재 제안 된 솔루션보다 훨씬 간단합니다.

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

다른 유형의 제약 조건을 삭제해야하는 경우 두 번째 매개 변수 위치에서 OBJECT_ID () 함수에 전달할 수있는 해당 코드는 다음과 같습니다.

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

두 번째 매개 변수없이 OBJECT_ID를 사용할 수도 있습니다.

전체 유형 목록은 다음과 같습니다.

객체 유형 :

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

적용 대상 : SQL Server 2012에서 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
여기 에 유형의 전체 목록 (즉, 키뿐만 아니라 모든 종류의 물건 에 적용).
ruffin

2
링크와 유형 목록을 추가 할 자유를 얻었습니다.
Mitch Wheat

10
제약 조건이 dbo 스키마에 없으면 스키마 이름도 포함해야합니다. 예 : OBJECT_ID ( 'MySchema.FK_MyConstraint', 'F')
Giles Smith

1
이 방법은 더 간단 할 수 있지만 다른 방법은 제약 조건을 명시 적으로 찾고 제거하는 데 더 좋으며 다른 테이블 / 스키마 / 데이터베이스에 동일한 이름을 가진 제약 조건도 포함됩니다.
CSS

1
여기에 하나의 문제가 있습니다. 포함을 삭제하는 테이블에 포함이 있는지 확인하지 않습니다.
sandeep rawat 2018 년


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

14

James의 답변 은 실제 제약 조건의 이름을 알고 있으면 잘 작동합니다. 까다로운 점은 레거시 및 기타 실제 시나리오 에서는 제약 조건이 무엇인지 수 없다는 입니다.

이 경우 중복 구속 조건을 작성할 위험이 있으므로 다음을 사용할 수 있습니다.

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

5
ALTER TABLE [dbo].[TableName]
    DROP CONSTRAINT FK_TableName_TableName2

5
아마도 그것을 TRY..CATCH블록에 넣을 것입니다 .
onedaywhen

"... SQL Server에있는 경우? ..."-해당 제약 조건이 있는지 어떻게 확인합니까?
new2ios

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

테이블에 여러 개의 외래 키가있을 수 있으므로 sys.foreign_keys에서 select에 필터로 이름을 포함시키는 것만 추가하면됩니다.
Koenyn

1

나는 이것이 당신에게 도움이 될 것이라고 생각합니다 ...

    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)

특정 테이블과 열을 기준으로 외래 키 제약 조건을 삭제합니다.


0

해당 쿼리를 사용하여 테이블에 대한 모든 FK를 찾을 수 있습니다.

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

이 질문에 대한 대답은 효과가없는 것 같습니다. 약간 다른 방법으로 같은 것을 달성했습니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.