Как удалить столбец, который имеет ограничение по умолчанию в SQL Server 2008?
Мой запрос
alter table tbloffers
drop column checkin
Я получаю ошибку ниже
ALTER TABLE DROP COLUMN не удалось выполнить проверку, поскольку один или несколько объектов обращаются к этому столбцу.
Может ли кто-нибудь исправить мой запрос, чтобы удалить столбец с ограничением?
sql-server
sql-server-2008
Робин Майкл Путураи
источник
источник
Ответы:
Сначала вы должны отбросить проблемный
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
источник
Вот еще один способ отбросить ограничение по умолчанию с неизвестным именем без предварительного запуска отдельного запроса для получения имени ограничения:
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)
источник
Вы также можете удалить столбец и его ограничения в одном выражении, а не по отдельности.
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);
источник
DROP CONSTRAINT
просмотра грамматики. Если вы не укажете ограничения явно, вам придется искать сгенерированное для него имя SQL Server, например, в соответствии с ответом Марка. Но, обнаружив это, вы все равно можете удалить ограничение и столбец одновременно.Найдите ограничение по умолчанию с помощью этого запроса здесь:
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
источник
ALTER TABLE table DROP CONSTRAINT DF_XY DROP COLUMN XY
К сожалению, синтаксис этого утверждения неверенDROP
командами, чтобы это сработалоСледующее работало для меня против бэкэнда SQL Azure (с использованием SQL Server Management Studio), поэтому YMMV, но, если это работает для вас, это вааааай проще, чем другие решения.
ALTER TABLE MyTable DROP CONSTRAINT FK_MyColumn CONSTRAINT DK_MyColumn -- etc... COLUMN MyColumn GO
источник
У меня то же самое:
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
источник
Я немного обновил скрипт для своей версии 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;
источник
Это не всегда просто ограничение по умолчанию, которое предотвращает удаление столбца, и иногда индексы также могут заблокировать вам удаление ограничения. Поэтому я написал процедуру, которая удаляет любой индекс или ограничение для столбца и самого столбца в конце.
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 = '' ;
источник