210

In SQL Server, I have a new column on a table:

ALTER TABLE t_tableName 
    ADD newColumn NOT NULL

This fails because I specify NOT NULL without specifying a default constraint. The table should not have a default constraint.

To get around this, I could create the table with the default constraint and then remove it.

However, there doesn't appear to be any way to specify that the default constraint should be named as part of this statement, so my only way to get rid of it is to have a stored procedure which looks it up in the sys.default_constraints table.

This is a bit messy/verbose for an operation which is likely to happen a lot. Does anyone have any better solutions for this?

Himanshu
  • 31,810
  • 31
  • 111
  • 133
GlennS
  • 5,251
  • 6
  • 28
  • 31

5 Answers5

297

This should work:

ALTER TABLE t_tableName 
    ADD newColumn VARCHAR(50)
    CONSTRAINT YourContraintName DEFAULT '' NOT NULL
Joe Stefanelli
  • 132,803
  • 19
  • 237
  • 235
  • 1
    Works in 2012 too. Gory details: http://msdn.microsoft.com/en-us/library/ms187742.aspx – adam77 Nov 16 '12 at 23:35
  • 26
    Why not put the `NOT NULL` adjacent to the data type? It may be syntactically valid to put it after the constraint, but it seems confusing to put it there. – Tullo_x86 Jan 07 '19 at 17:14
  • 1
    @Tullo_x86 The "Generate scripts..." tools in SSMS and SSDT still default to putting the `NOT NULL` part at the very end of the line after the type, default constraint, and temporal-table `GENERATED` bits. It's hideous. – Dai Nov 14 '21 at 12:17
138
ALTER TABLE t_tableName 
    ADD newColumn int NOT NULL
        CONSTRAINT DF_defaultvalue DEFAULT (1)
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • 28
    I prefer this to the accepted answer as I can drop the default constraint without worrying about losing the NOT NULL constraint. – EleventhDoctor Sep 02 '14 at 12:22
  • 11
    @EleventhDoctor That makes no sense. The NOT NULL is not part of the constraint and the drop statement just references the constraint name – Roger Willcocks Mar 29 '16 at 00:07
  • 15
    @RogerWillcocks You are right, but it is clearer upon reading it that the NOT NULL is separate from the constraint. – deluxxxe Jan 26 '17 at 15:47
48

I would like to add some details:

The most important hint is: You should never-ever create a constraint without an explicit name!

The biggest problem with unnamed constraints: When you execute this on various customer machines, you will get different/random names on each.
Any future upgrade script will be a real headache...

The general advise is:

  • No constraint without a name!
  • Use some naming convention e.g.
    • DF_TableName_ColumnName for a default constraint
    • CK_TableName_ColumnName for a check constraint
    • UQ_TableName_ColumnName for a unique constraint
    • PK_TableName for a primary key constraint

The general syntax is

TheColumn <DataType> Nullability CONSTRAINT ConstraintName <ConstraintType> <ConstraintDetails>

Try this here

You can add more constraints to each column and you can add additional constraints just as you add columns after a comma:

CREATE TABLE dbo.SomeOtherTable(TheIdThere INT NOT NULL CONSTRAINT PK_SomeOtherTable PRIMARY KEY)
GO
CREATE TABLE dbo.TestTable
(
 --define the primary key
 ID INT IDENTITY NOT NULL CONSTRAINT PK_TestTable PRIMARY KEY

 --let the string be unique (results in a unique index implicitly)
,SomeUniqueString VARCHAR(100) NOT NULL CONSTRAINT UQ_TestTable_SomeUniqueString UNIQUE

 --define two constraints, one for a default value and one for a value check
,SomeNumber INT NULL CONSTRAINT DF_TestTable_SomeNumber DEFAULT (0)
                     CONSTRAINT CK_TestTable_SomeNumber_gt100 CHECK(SomeNumber>100)

 --add a foreign key constraint
,SomeFK INT NOT NULL CONSTRAINT FK_TestTable_SomeFK FOREIGN KEY REFERENCES dbo.SomeOtherTable(TheIdThere)

 --add a constraint for two columns separately
,CONSTRAINT UQ_TestTable_StringAndNumber UNIQUE(SomeFK,SomeNumber)
);
GO

--insert some data

INSERT INTO dbo.SomeOtherTable VALUES(1);
INSERT INTO dbo.TestTable(SomeUniqueString,SomeNumber,SomeFK) VALUES('hello',111,1);
GO
INSERT INTO dbo.TestTable(SomeUniqueString,SomeNumber,SomeFK) 
VALUES('fails due to uniqueness of 111,1',111,1);
Shnugo
  • 66,100
  • 9
  • 53
  • 114
  • The top 2 answers both name their constraints, so your statement "I would like to add some details, as the existing answers are rather thin: The most important hint is: You should never-ever create a constraint without an explicit name!" - seems somewhat redundant. – Mitch Wheat Jul 28 '20 at 06:41
2

Try like below script-

ALTER TABLE DEMO_TABLE
ADD Column1 INT CONSTRAINT Def_Column1 DEFAULT(3) NOT NULL,
    Column2 VARCHAR(10) CONSTRAINT Def_Column2 DEFAULT('New') NOT NULL;
GO
Arulmouzhi
  • 1,878
  • 17
  • 20
-1

I use the following when adding new columns and defaults to large tables. Execute each line separately:

ALTER TABLE dbo.[TableName] ADD [ColumnName] BIT NULL; /*null>no table rebuild*/

UPDATE rf SET rf.[ColumnName] = 0 FROM dbo.[TableName] rf WHERE rf.[ColumnName] IS NULL;

ALTER TABLE dbo.[TableName] ALTER COLUMN [ColumnName] BIT NOT NULL;

ALTER TABLE dbo.[TableName] ADD CONSTRAINT DF_[TableName]_[ColumnName] DEFAULT 0 FOR [ColumnName];
mortenma71
  • 1,078
  • 2
  • 9
  • 27