Reputation: 5664
How to drop a column which is having Default constraint in SQL Server 2008?
My query is
alter table tbloffers
drop column checkin
I am getting below error
ALTER TABLE DROP COLUMN checkin failed because one or more objects access this column.
Can anyone correct my query to drop a column with constraint?
Upvotes: 192
Views: 344451
Reputation: 1367
@chris-halcrow's answer was great indeed but it does not work in 2024 anymore. here is the updated version of the same.
DECLARE @ConstraintName NVARCHAR(200)
SELECT @ConstraintName = name FROM SYS.default_constraints WHERE object_id = (
SELECT default_object_id FROM sys.columns WHERE name = '<ColumnName>'
)
IF @ConstraintName IS NOT NULL
EXEC('ALTER TABLE <TableName> DROP CONSTRAINT ' + @ConstraintName)
Upvotes: 1
Reputation: 3233
There are some built in tools availabe in the SQL Server that can make life easy for developers.
CREATE TABLE demo..Person (
PersonID int default 0,
LastName varchar(255),
)
-- Dropping the Column
alter table demo..Person drop column PersonID
The object 'DF__Person__PersonID__0DE74436' is dependent on column 'PersonID'.
Msg 4922, Level 16, State 9, Line 8
ALTER TABLE DROP COLUMN PersonID failed because one or more objects access this column.
Solution using the design tool of SQL Server 2019.
Upvotes: 0
Reputation: 143
a bit simpler drop constraint by table name and column name:
DECLARE @ConstraintName NVARCHAR(100)
SELECT @ConstraintName = OBJECT_NAME([default_object_id])
FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[my_table_name]') AND [name] = 'my_column_name';
EXEC('ALTER TABLE [my_table_name] DROP CONSTRAINT ' + @ConstraintName)
Upvotes: 5
Reputation: 3510
Based on the previous answers, I have added it as a stored procedure to simplify the deletion of a column when it has attached constraints
CREATE OR ALTER PROC DROP_COLUMN(@TableName nvarchar(200), @ColumnName nvarchar(200))
AS
BEGIN
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 = @ColumnName
AND object_id = OBJECT_ID(@TableName))
IF @ConstraintName IS NOT NULL
EXEC('ALTER TABLE '+@TableName+' DROP CONSTRAINT ' + @ConstraintName)
EXEC('ALTER TABLE '+@TableName+' DROP COLUMN IF EXISTS ' + @ColumnName)
END
GO
--example:
EXEC DROP_COLUMN N'VEHICLES', N'SCMT'
EXEC DROP_COLUMN N'VEHICLES', N'SSC'
EXEC DROP_COLUMN N'VEHICLES', N'RS'
EXEC DROP_COLUMN N'VEHICLES', N'RCEC'
DROP PROCEDURE IF EXISTS DROP_COLUMN
Upvotes: 3
Reputation: 41
It's not always just a default constraint that prevents from droping a column and sometimes indexes can also block you from droping the constraint. So I wrote a procedure that drops any index or constraint on a column and the column it self at the end.
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 ([email protected] 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 = ''
;
Upvotes: 2
Reputation: 31
I have updated script a little bit to my SQL server version
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;
Upvotes: 3
Reputation: 6412
The following worked for me against a SQL Azure backend (using SQL Server Management Studio), so YMMV, but, if it works for you, it's waaaaay simpler than the other solutions.
ALTER TABLE MyTable
DROP CONSTRAINT FK_MyColumn
CONSTRAINT DK_MyColumn
-- etc...
COLUMN MyColumn
GO
Upvotes: 3
Reputation: 453288
You can also drop the column and its constraint(s) in a single statement rather than individually.
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
(but not other possible column dependencies such as foreign keys, unique and primary key constraints, computed columns, indexes)
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);
Upvotes: 32
Reputation: 21766
First you should drop the problematic DEFAULT constraint
, after that you can drop the column
alter table tbloffers drop constraint [ConstraintName]
go
alter table tbloffers drop column checkin
But the error may appear from other reasons - for example the user defined function or view with SCHEMABINDING
option set for them.
UPD: Completely automated dropping of constraints script:
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
Upvotes: 299
Reputation: 5507
I got the same:
ALTER TABLE DROP COLUMN failed because one or more objects access this column message.
My column had an index which needed to be deleted first. Using sys.indexes did the trick:
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
Upvotes: 1
Reputation: 31950
Here's another way to drop a default constraint with an unknown name without having to first run a separate query to get the constraint name:
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)
Upvotes: 186
Reputation: 754518
Find the default constraint with this query here:
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
This gives you the name of the default constraint, as well as the table and column name.
When you have that information you need to first drop the default constraint:
ALTER TABLE dbo.YourTable
DROP CONSTRAINT name-of-the-default-constraint-here
and then you can drop the column
ALTER TABLE dbo.YourTable DROP COLUMN YourColumn
Upvotes: 30