72

I know the syntax:

ALTER TABLE [TheTable] DROP CONSTRAINT [TheDefaultConstraint]

but how to I drop the default constraint when I don't know its name? (That is, it was autogenerated at CREATE TABLE time.)

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Frank Krueger
  • 69,552
  • 46
  • 163
  • 208

6 Answers6

69

You can use this code to do it automatically:

DECLARE @tableName VARCHAR(MAX) = '<MYTABLENAME>'
DECLARE @columnName VARCHAR(MAX) = '<MYCOLUMNAME>'
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)

Just replace <MYTABLENAME> and <MYCOLUMNNAME> as appropriate.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Polemarch
  • 1,646
  • 14
  • 10
  • 5
    For lazy people, (and Microsoft's SQL Server developers), in homage to this answer, replace the top two lines with `CREATE PROCEDURE dbo.DropColumnDefaultOrConstraint @tableName VARCHAR(MAX), @columnName VARCHAR(MAX) AS` then wrap in `BEGIN` and `END` and use `EXEC DropColumnDefaultOrConstraint 'tablename', 'columnname';` – Chris May 02 '15 at 11:53
  • 10
    I just don't understand why MS SQL doesn't automatically drop default constraints. – Tim Jul 12 '16 at 15:57
  • 1
    this automated script is essential for any roll-your-own database schema update engine. I wonder how EF migration tool does that? the underlying flaw, that SQL server generates names for anonymous defaults and requires you to know/obtain that name in order to change or drop it again, is an issue which should have been addressed in tsql syntax itself long ago. but it is still around in sql2016. @Tim yes, or at least a syntax to force the drop. – Cee McSharpface Aug 31 '16 at 09:13
  • @dlatikay EF doesn't handle default constraints. It won't create them by default (since there is no way to set them with attributes or fluent api), but if you manually add them EF will never check to remove them on other changes. I don't know if this is true with Automatic migrations though. – Tim Aug 31 '16 at 11:13
  • 1
    @Tim the current version of EF can do it. I looked it up out of curiosity, and their approach is very similar: they retrieve the name from `sys.default_constraints`; look in line 577 and following, [here](https://github.com/aspnet/EntityFramework/blob/bbc83e8971e550a449b730e06adf8cfded323d9c/src/Microsoft.EntityFrameworkCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs) – Cee McSharpface Aug 31 '16 at 13:38
  • @dlatikay Oh thanks, good to know they fixed in the EF Core. I am still on 6. Worth the upgrade? – Tim Aug 31 '16 at 14:31
50

If you want to do this manually, you can use Management Studio to find it (under the Constraints node inside the table).

To do it using SQL:

  • If the constraints are default constraints, you can use sys.default_constraints to find it:

    SELECT OBJECT_NAME(parent_object_id) AS TableName, name AS ConstraintName
    FROM sys.default_constraints ORDER BY TableName, ConstraintName
    
  • If you are looking for other constraints as well (check, unique, foreign key, default, primary key), you can use sysconstraints:

    SELECT OBJECT_NAME(id) AS TableName, OBJECT_NAME(constid) AS ConstraintName
    FROM sysconstraints ORDER BY TableName, ConstraintName
    

You do not say which version of SQL Server you are using. The above work on both SQL 2005 and SQL 2008.

adrianbanks
  • 81,306
  • 22
  • 176
  • 206
  • The first query worked great in SQL 2008 r2 when I found the table's objectID first with `DECLARE @ParentObjectId INT = (select OBJECT_ID from sys.objects where name = 'ParentTable' AND type = 'U')` and added `WHERE parent_object_id = @ParentObjectId` to the query. Otherwise you're getting all of the default constraints in the database. – Torrents Jan 27 '15 at 01:13
  • This is nice, but it doesn't show the schema the tables are in. It would be nice if you added a join to sys.schemas. – AperioOculus Feb 01 '17 at 20:15
  • If you know the table name add a WHERE clause to the SELECT so you don't have to search in a possibly long list of table names. The auto generated names seem to contain truncated parts of the table and column name, which will let you identify the correct constraint. Good luck! – Marcell Apr 10 '18 at 08:42
4

You can find the name of the constraint out by sp_help [table name] and then drop it by name.

Or you can probably do this via Management studio.

Tetraneutron
  • 32,841
  • 3
  • 25
  • 21
4

Or you can find it using sys.check_constraints catalog view.

Alex_L
  • 2,658
  • 1
  • 15
  • 13
2

For a single table and column in a single line use the following

declare @sql nvarchar(max); set @sql = ''; SELECT @sql+='ALTER TABLE [dbo].[YOURTABLENAME] DROP CONSTRAINT ' + ((SELECT OBJECT_NAME(constid) FROM sysconstraints WHERE OBJECT_NAME(id) = 'YOURTABLENAME'AND colid IN (SELECT ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS Where Table_Name = 'YOURTABLENAME' and COLUMN_NAME = 'YOURCOLUMNNAM'))) + ';'; EXEC sp_executesql @sql;

If you have multiple constraints on the column you will need to discriminate on the constraint you are after, but if you just have a default constraint this will do the trick.

Check out the other columns available in the information_schema to allow you to discriminate further.

sweetfa
  • 5,457
  • 2
  • 48
  • 62
0

Here goes my own version that drops all dependent constraints -- default constraint (if exists) and all affected check constraints (as SQL standard seems to suggest and as some other databases seem to so)

declare @constraints varchar(4000);
declare @sql varchar(4000);
with table_id_column_position as (
   select object_id table_id, column_id column_position
      from sys.columns where object_id is not null and object_id = object_id('TableName') and name = 'ColumnToBeDropped'
)
select @constraints = coalesce(@constraints, 'constraint ') + '[' + name + '], '
from sysobjects 
where (
  -- is CHECK constraint
  type = 'C' 
  -- dependeds on the column
  and id is not null
  and id in (
      select object_id --, object_name(object_id)
      from sys.sql_dependencies, table_id_column_position 
      where object_id is not null
      and referenced_major_id = table_id_column_position.table_id
      and referenced_minor_id = table_id_column_position.column_position
    )
) OR (
  -- is DEFAULT constraint
  type = 'D'
  and id is not null
  and id in (
    select object_id
    from sys.default_constraints, table_id_column_position
     where object_id is not null
     and parent_object_id = table_id_column_position.table_id
     and parent_column_id = table_id_column_position.column_position
  )
);
set @sql = 'alter table TableName drop ' + coalesce(@constraints, '') + ' column ColumnToBeDropped';
exec @sql

(Beware: both TableName and ColumnToBeDropped appear twice in the code above)

This works by constructing single ALTER TABLE TableName DROP CONSTRAINT c1, ..., COLUMN ColumnToBeDropped and executing it.

Piotr Findeisen
  • 19,480
  • 2
  • 52
  • 82