제약 조건으로 열을 삭제하는 방법은 무엇입니까?


138

SQL Server 2008에서 기본 제약 조건이있는 열을 삭제하는 방법은 무엇입니까?

내 질문은

alter table tbloffers
drop column checkin

오류가 발생합니다

하나 이상의 오브젝트가이 컬럼에 액세스하므로 ALTER TABLE DROP COLUMN 체크인에 실패했습니다.

누구나 내 쿼리를 수정하여 제약 조건이있는 열을 삭제할 수 있습니까?


이 오류를 발생시키는 다른 테이블에서이 테이블에 대한 일부 참조가있을 수 있습니다.
Pankaj Upadhyay

이에 대한 새로운 이민자들을 위해 아래의 답변을 확인하십시오 .
BrainSlugs83

나는 나의 질문과 답변을 여기에
Akash Yellappa

답변:


233

먼저 문제가있는을 삭제해야합니다. DEFAULT constraint그 후에 열을 삭제할 수 있습니다

alter table tbloffers drop constraint [ConstraintName]
go

alter table tbloffers drop column checkin

그러나 다른 이유로 인해 오류가 나타날 수 있습니다 (예 : 사용자 정의 함수 또는 SCHEMABINDING옵션이 설정된 보기) .

UPD : 완전 자동 구속 조건 제거 스크립트 :

DECLARE @sql NVARCHAR(MAX)
WHILE 1=1
BEGIN
    SELECT TOP 1 @sql = N'alter table tbloffers drop constraint ['+dc.NAME+N']'
    from sys.default_constraints dc
    JOIN sys.columns c
        ON c.default_object_id = dc.object_id
    WHERE 
        dc.parent_object_id = OBJECT_ID('tbloffers')
    AND c.name = N'checkin'
    IF @@ROWCOUNT = 0 BREAK
    EXEC (@sql)
END

1
자동화 된 스크립트에 감사드립니다. 매력처럼 작동합니다!
kanadianDri3

정말 감사합니다. 시간을 많이 절약했습니다. 나는 여기에 요청한 질문을 연결했습니다
Akash Yellappa

130

제약 조건 이름을 얻기 위해 먼저 별도의 쿼리를 실행하지 않고도 알 수없는 이름으로 기본 제약 조건을 삭제하는 또 다른 방법이 있습니다.

DECLARE @ConstraintName nvarchar(200)
SELECT @ConstraintName = Name FROM SYS.DEFAULT_CONSTRAINTS
WHERE PARENT_OBJECT_ID = OBJECT_ID('__TableName__')
AND PARENT_COLUMN_ID = (SELECT column_id FROM sys.columns
                        WHERE NAME = N'__ColumnName__'
                        AND object_id = OBJECT_ID(N'__TableName__'))
IF @ConstraintName IS NOT NULL
EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + @ConstraintName)

훌륭한 답변입니다. 감사합니다. 그래도 떨어지기를 결정하기 전에 먼저 선택하고 검사하는 오래된 습관에서 위의 답변을 찬성했습니다.
noogrub

7
실제로 큰 대답입니다. 나는 편리 / 미래의 사용을 위해 그것을 저장 프로 시저를 만든 : pastebin.com/2CeXZDh2이
파고

열에 연결된 제약 조건이 둘 이상인 경우 탁월한 대답이지만 여전히 접근 방식이 누락되었습니다. 별 5 개 수에 포함 루프 @Digs '포스트와 비슷한 저장 시저 대답
YeinCM-Qva에게

27

열과 제약 조건을 개별적으로가 아니라 단일 문으로 삭제할 수도 있습니다.

CREATE TABLE #T
  (
     Col1 INT CONSTRAINT UQ UNIQUE CONSTRAINT CK CHECK (Col1 > 5),
     Col2 INT
  )

ALTER TABLE #T DROP CONSTRAINT UQ , 
                    CONSTRAINT CK, 
                    COLUMN Col1


DROP TABLE #T 

종속 검사 제한 조건 및 기본 제한 조건의 이름을 찾아서 열과 함께 삭제하는 일부 동적 SQL은 다음과 같습니다.

(단, 외래 키, 고유 및 기본 키 제약 조건, 계산 열, 인덱스와 같은 다른 가능한 열 종속성은 아님)

CREATE TABLE [dbo].[TestTable]
(
A INT DEFAULT '1' CHECK (A=1),
B INT,
CHECK (A > B)
)

GO

DECLARE @TwoPartTableNameQuoted nvarchar(500) = '[dbo].[TestTable]',
        @ColumnNameUnQuoted sysname = 'A',
        @DynSQL NVARCHAR(MAX);

SELECT @DynSQL =
     'ALTER TABLE ' + @TwoPartTableNameQuoted + ' DROP' + 
      ISNULL(' CONSTRAINT ' + QUOTENAME(OBJECT_NAME(c.default_object_id)) + ',','') + 
      ISNULL(check_constraints,'') + 
      '  COLUMN ' + QUOTENAME(@ColumnNameUnQuoted)
FROM   sys.columns c
       CROSS APPLY (SELECT ' CONSTRAINT ' + QUOTENAME(OBJECT_NAME(referencing_id)) + ','
                    FROM   sys.sql_expression_dependencies
                    WHERE  referenced_id = c.object_id
                           AND referenced_minor_id = c.column_id
                           AND OBJECTPROPERTYEX(referencing_id, 'BaseType') = 'C'
                    FOR XML PATH('')) ck(check_constraints)
WHERE  c.object_id = object_id(@TwoPartTableNameQuoted)
       AND c.name = @ColumnNameUnQuoted;

PRINT @DynSQL;
EXEC (@DynSQL); 

그래야 구속 조건의 이름을 알아야합니다. 테이블 작성 중에 이름을 지정하지 않은 경우 자동으로 생성 된 이름을 얻습니다.
Joey

1
@Joey-이름을 모르면 제약 조건을 삭제하는 구문이 없습니다. DROP CONSTRAINT 문법보려면 필수 인수입니다 . 제약 조건의 이름을 명시 적으로 지정하지 않으면 마크의 답변에 따라 SQL Server에 대해 생성 된 이름을 찾아야합니다. 그러나 제약 조건과 열을 동시에 삭제할 수 있다는 것을 알았습니다.
Martin Smith

좋은 코드, 한 번에 여러 제약 조건을 삭제해야했지만 열은 필요하지 않았습니다. 당신의 변경은 트릭을했다. 감사!!
htm11h

26

이 쿼리에서 기본 제약 조건을 찾으십시오.

SELECT
    df.name 'Constraint Name' ,
    t.name 'Table Name',
    c.NAME 'Column Name'
FROM sys.default_constraints df
INNER JOIN sys.tables t ON df.parent_object_id = t.object_id
INNER JOIN sys.columns c ON df.parent_object_id = c.object_id AND df.parent_column_id = c.column_id

기본 제한 조건의 이름과 테이블 및 열 이름이 제공됩니다.

해당 정보가 있으면 먼저 기본 제한 조건을 삭제해야합니다.

ALTER TABLE dbo.YourTable
DROP CONSTRAINT name-of-the-default-constraint-here

그런 다음 열을 삭제할 수 있습니다

ALTER TABLE dbo.YourTable DROP COLUMN YourColumn

2
순차적으로 수행 할 필요는 없습니다. 동시에 둘 다 할 수 있습니다.
Martin Smith

1
@MartinSmith : 좋아요, 좋아요-공유해 주셔서 감사합니다! 나는이 가능성을 몰랐다 – 당신은 매일 새로운 것을 배운다! :-)
marc_s

누군가이 두 진술을 결합하는 방법에 대한 예를 제공 할 수 있습니까? 다음과 같은 생각이 필요합니다. ALTER TABLE table DROP CONSTRAINT DF_XY DROP COLUMN XY불행히도이 문장의 구문이 올바르지 않습니다
My-Name-Is

1
내-이름-IS @ : 당신이 마틴의 답변을 확인하면, 당신은 둘 필요가 쉼표 둘 사이 DROP이 작동하도록 명령을
marc_s

3

다음은 SQL Azure 백엔드 (SQL Server Management Studio 사용), YMMV에 대해 나에게 도움이되었지만 그것이 효과가 있다면 다른 솔루션보다 훨씬 간단합니다.

ALTER TABLE MyTable
    DROP CONSTRAINT FK_MyColumn
    CONSTRAINT DK_MyColumn
    -- etc...
    COLUMN MyColumn
GO

1

나는 같은 것을 얻었다 :

하나 이상의 객체가이 열 메시지에 액세스하기 때문에 ALTER TABLE DROP COLUMN이 실패했습니다 .

내 열에 인덱스를 먼저 삭제해야했습니다. sys.indexes를 사용 하여 트릭을 수행했습니다.

DECLARE @sql VARCHAR(max)

SELECT @sql = 'DROP INDEX ' + idx.NAME + ' ON tblName'
FROM sys.indexes idx
INNER JOIN sys.tables tbl ON idx.object_id = tbl.object_id
INNER JOIN sys.index_columns idxCol ON idx.index_id = idxCol.index_id
INNER JOIN sys.columns col ON idxCol.column_id = col.column_id
WHERE idx.type <> 0
    AND tbl.NAME = 'tblName'
    AND col.NAME = 'colName'

EXEC sp_executeSql @sql
GO

ALTER TABLE tblName
DROP COLUMN colName

0

스크립트를 SQL Server 버전으로 약간 업데이트했습니다.

DECLARE @sql nvarchar(max)

SELECT @sql = 'ALTER TABLE `table_name` DROP CONSTRAINT ' + df.NAME 
FROM sys.default_constraints df
  INNER JOIN sys.tables t ON df.parent_object_id = t.object_id
  INNER JOIN sys.columns c ON df.parent_object_id = c.object_id AND df.parent_column_id = c.column_id
where t.name = 'table_name' and c.name = 'column_name'

EXEC sp_executeSql @sql
GO

ALTER TABLE table_name
  DROP COLUMN column_name;

0

항상 열을 삭제하지 못하게하는 기본 제약 조건은 아니며 때로는 인덱스를 사용하여 제약 조건을 삭제하지 못할 수도 있습니다. 그래서 열과 인덱스가 끝날 때마다 인덱스 또는 제약 조건을 삭제하는 절차를 작성했습니다.

IF OBJECT_ID ('ADM_delete_column', 'P') IS NOT NULL
   DROP procedure ADM_delete_column;
GO

CREATE procedure ADM_delete_column
    @table_name_in  nvarchar(300)
,   @column_name_in nvarchar(300)
AS 
BEGIN
    /*  Author: Matthis (matthis@online.ms at 2019.07.20)
        License CC BY (creativecommons.org)
        Desc:   Administrative procedure that drops columns at MS SQL Server
                - if there is an index or constraint on the column 
                    that will be dropped in advice
                => input parameters are TABLE NAME and COLUMN NAME as STRING
    */
    SET NOCOUNT ON

    --drop index if exist (search first if there is a index on the column)
    declare @idx_name VARCHAR(100)
    SELECT  top 1 @idx_name = i.name
    from    sys.tables t
    join    sys.columns c
    on      t.object_id = c.object_id
    join    sys.index_columns ic
    on      c.object_id = ic.object_id
    and     c.column_id = ic.column_id
    join    sys.indexes i
    on      i.object_id = ic.object_id
    and     i.index_id = ic.index_id
    where   t.name like @table_name_in
    and     c.name like @column_name_in
    if      @idx_name is not null
    begin 
        print concat('DROP INDEX ', @idx_name, ' ON ', @table_name_in)
        exec ('DROP INDEX ' + @idx_name + ' ON ' + @table_name_in)
    end

    --drop fk constraint if exist (search first if there is a constraint on the column)
    declare @fk_name VARCHAR(100)
    SELECT  top 1 @fk_name = CONSTRAINT_NAME 
    from    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
    where   TABLE_NAME like @table_name_in
    and     COLUMN_NAME like @column_name_in
    if      @fk_name is not null
    begin 
        print concat('ALTER TABLE ', @table_name_in, ' DROP CONSTRAINT ', @fk_name)
        exec ('ALTER TABLE ' + @table_name_in + ' DROP CONSTRAINT ' + @fk_name)
    end

    --drop column if exist
    declare @column_name VARCHAR(100)
    SELECT  top 1 @column_name = COLUMN_NAME 
    FROM    INFORMATION_SCHEMA.COLUMNS 
    WHERE   COLUMN_NAME like concat('%',@column_name_in,'%')
    if  @column_name is not null
    begin 
        print concat('ALTER TABLE ', @table_name_in, ' DROP COLUMN ', @column_name)
        exec ('ALTER TABLE ' + @table_name_in + ' DROP COLUMN ' + @column_name)
    end
end;
GO


--to run the procedure use this execute and fill the parameters 
execute ADM_delete_column 
    @table_name_in  = ''
,   @column_name_in = ''
    ;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.