Как удалить столбец с ограничением? - PullRequest
115 голосов
/ 27 декабря 2011

Как удалить столбец с ограничением по умолчанию в SQL Server 2008?

Мой запрос

alter table tbloffers
drop column checkin

Ошибка ниже

Ошибка регистрации ALTER TABLE DROP COLUMN, поскольку один или несколько объектов обращаются к этому столбцу.

Может ли кто-нибудь исправить мой запрос, чтобы удалить столбец с ограничением?

Ответы [ 7 ]

200 голосов
/ 27 декабря 2011

Сначала вы должны сбросить проблемный 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
113 голосов
/ 05 декабря 2012

Вот еще один способ удалить ограничение по умолчанию с неизвестным именем без необходимости сначала запускать отдельный запрос, чтобы получить имя ограничения:

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)
23 голосов
/ 27 декабря 2011

Найти ограничение по умолчанию с помощью этого запроса здесь:

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
22 голосов
/ 28 декабря 2011

Вы также можете удалить столбец и его ограничения в одном выражении, а не по отдельности.

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); 
2 голосов
/ 04 октября 2017

Следующее сработало для меня с бэкэндом SQL Azure (с использованием SQL Server Management Studio), поэтому YMMV, но, если он работает для вас, он намного проще, чем другие решения.

ALTER TABLE MyTable
    DROP CONSTRAINT FK_MyColumn
    CONSTRAINT DK_MyColumn
    -- etc...
    COLUMN MyColumn
GO
1 голос
/ 20 мая 2013

Я получил то же самое:

Ошибка 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 голосов
/ 21 мая 2019

Я немного обновил скрипт до версии моего сервера SQL

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;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...