69

I'm trying to create upgrade and backout scripts in SQL. The upgrade script adds a column like so:

IF NOT EXISTS (SELECT * FROM sys.columns WHERE Name = N'ColumnName' 
    AND object_id = OBJECT_ID(N'[dbo].[TableName]'))

ALTER TABLE TableName
    ADD ColumnName bit NOT NULL DEFAULT(0) 

The backout script removes the column like so:

IF EXISTS (SELECT * FROM sys.columns WHERE Name = N'ColumnName' 
    AND object_id = OBJECT_ID(N'[dbo].[TableName]'))

ALTER TABLE TableName
    DROP COLUMN ColumnName

However, the backout script throws this error:

Msg 5074, Level 16, State 1, Line 5
    The object 'DF__TableName__ColumnName__1BF3D5BD' is dependent on column 'ColumnName'.
Msg 4922, Level 16, State 9, Line 5
    ALTER TABLE DROP COLUMN ColumnName failed because one or more objects access this column.

I know how to drop the constraint, but the constraint's name changes everytime (the suffix changes). I either need SQL Server to stop creating this randomly-named constraint OR I need to be able to remove the constraint in my script using wild-card characters, since the name changes.

4 Answers 4

115

This is the default constraint that is added because of the DEFAULT(0) in your newly added column.

You can name this yourself so it has a known fixed name rather than relying on the auto name generation.

ALTER TABLE TableName
    ADD ColumnName bit NOT NULL CONSTRAINT DF_Some_Fixed_Name DEFAULT(0) 

Then to remove the column and constraint together

ALTER TABLE dbo.TableName
DROP CONSTRAINT DF_Some_Fixed_Name, COLUMN ColumnName
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Martin. Also, to properly check if the constraint exists (before dropping it), I used the method described here
@ÁlvaroG.Vicario - yes. Martin's answer gives you an example.
6

Run this:

declare @name as nvarchar(255);
SELECT @name = name FROM dbo.sysobjects 
WHERE name LIKE 'DF__XXX__YYY__%' and type = 'D'

IF @name IS NOT NULL BEGIN
    EXEC('ALTER TABLE XXX DROP CONSTRAINT ' + @name);
END

2 Comments

Do we need to change any of the XXX/YYY to something specific?
XXX is the tablename and YYY is the column name. The names will probably be shortened to 6 characters though.
2

Run this if you want remove constraint:

DECLARE @tableName NVARCHAR(255) = '[INSERT]';
DECLARE @first5CharsFromColumnName NVARCHAR(255) = '[INSERT]';
DECLARE @name NVARCHAR(255);
SELECT @name = d.name FROM dbo.sysobjects d
INNER JOIN dbo.sysobjects t ON t.id = d.parent_obj
WHERE d.name LIKE '%'+@first5CharsFromColumnName+'%' AND d.type = 'D' AND t.name = @tableName

IF @name IS NOT NULL BEGIN
    EXEC('ALTER TABLE '+@tableName+' DROP CONSTRAINT ' + @name);
END

1 Comment

This was very helpful! I prefer it to my approach of capturing the parent_obj id number, as it uses Join instead.
0

Other answers are great; in my case, the table name was also too long, so I ended up with something like this:

DECLARE @tableName NVARCHAR(255) = '[INSERT TABLE NAME WITHOUT dbo. PREFIX]';
DECLARE @columnName NVARCHAR(255) = '[INSERT COLUMN NAME]';

DECLARE @first9CharsFromTableName NVARCHAR(9) = @tableName;
DECLARE @first5CharsFromColumnName NVARCHAR(5) = @columnName;

DECLARE @name NVARCHAR(255);

SELECT @name = d.name FROM dbo.sysobjects d
  INNER JOIN dbo.sysobjects t ON t.id = d.parent_obj
  WHERE d.name LIKE 'DF__'+@first9CharsFromTableName+'__'+@first5CharsFromColumnName+'__%' AND d.type = 'D' AND t.name = @tableName;

IF @name IS NOT NULL BEGIN
  EXEC('ALTER TABLE [dbo].' + @tableName + ' DROP CONSTRAINT ' + @name);
END

EXEC('ALTER TABLE [dbo].' + @tableName + ' DROP COLUMN ' + @columnName);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.