As an option you can initially create Null-able column, then update your table column with valid not null values and finally ALTER column to set NOT NULL constraint:

ALTER TABLE MY_TABLE ADD STAGE INT NULL
GO
UPDATE MY_TABLE SET <a valid not null values for your column>
GO
ALTER TABLE MY_TABLE ALTER COLUMN STAGE INT NOT NULL
GO

Another option is to specify correct default value for your column:

ALTER TABLE MY_TABLE ADD STAGE INT NOT NULL DEFAULT '0'

UPD: Please note that answer above contains GO which is a must when you run this code on Microsoft SQL server. If you want to perform the same operation on Oracle or MySQL you need to use semicolon ; like that:

ALTER TABLE MY_TABLE ADD STAGE INT NULL;
UPDATE MY_TABLE SET <a valid not null values for your column>;
ALTER TABLE MY_TABLE ALTER COLUMN STAGE INT NOT NULL;
Answer from Pavel Morshenyuk on Stack Overflow
🌐
W3Schools
w3schools.com › sql › sql_notnull.asp
SQL NOT NULL Constraint
The following SQL creates a "Persons" ... ); To define a NOT NULL constraint on an existing table, use ALTER TABLE and add NOT NULL after the data type of the column name....
Discussions

sql server - Alternate table with new not null Column in existing table in SQL - Stack Overflow
How to add not null Column in existing table in SQL Server 2005? More on stackoverflow.com
🌐 stackoverflow.com
April 25, 2018
scripting - SQL Server - Adding non-nullable column to existing table - SSDT Publishing - Database Administrators Stack Exchange
Due to business logic, we need a new column in a table that is critical to ensure is always populated. Therefore it should be added to the table as NOT NULL. Unlike previous questions that explain ... More on dba.stackexchange.com
🌐 dba.stackexchange.com
June 1, 2018
Add non-nullable columns to an existing table in SQL server? - Stack Overflow
I already have a table which consists of data. I need to alter the table to add two new columns which are not null. How can I do that without losing any existing data? Here's what I tried (via right- More on stackoverflow.com
🌐 stackoverflow.com
sql - Safely add a non-null column to an existing table - Stack Overflow
This is to prevent the ALTER COLUMN statement from failing because of a NULL value in MyColumn in the newly inserted row. Is there a better alternative to GO to ensure ADD [MyColumn] completes before SET [MyColumn] ? ... BEGIN TRANSACTION ALTER TABLE [MySchema].[MyTable] ADD [MyColumn] VARCHAR(10) NOT NULL CONSTRAINT MyTableDefault DEFAULT 'ValueForExistingData'; ALTER TABLE [MySchema].[MyTable] DROP CONSTRAINT MyTableDefault; COMMIT · On Enterprise edition SQL ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Qlik Community
community.qlik.com › t5 › Suggest-an-Idea › MS-SQL-Server-Adding-a-NOT-NULL-column-to-an-existing-table › idi-p › 1968370
MS SQL Server: Adding a NOT NULL column to an existing table
December 20, 2022 - It appears to execute a statement like this: ALTER <table> ADD <column> <data_type> NULL The key impact of this is when the source table has data in it prior to this change. In that case it results in material differences between source and target: ...
🌐
PopSQL
popsql.com › learn-sql › sql-server › how-to-add-a-not-null-constraint-in-sql-server
SQL Server Not Null: How to Add using Alter Table - PopSQL
Learn how to add a NOT NULL constraint in SQL Server for a specific column. Use the "ALTER TABLE" command with "ALTER COLUMN" and specify the "NOT NULL" attribute in the column definition to enforce data validation.
🌐
TutorialsPoint
tutorialspoint.com › how-to-add-a-not-null-column-in-mysql
How to add a NOT NULL column in MySQL?
mysql> create table AddNotNull -> ( -> Id int, -> Name varchar(100) -> ); Query OK, 0 rows affected (1.43 sec) Here is the query to add a not null column in an existing table using alter command.
🌐
Viget
viget.com › articles › adding-a-not-null-column-to-an-existing-table
Adding a NOT NULL Column to an Existing Table | Viget
March 9, 2016 - StandardError: An error has occurred, this and all later migrations canceled: SQLite3::SQLException: Cannot add a NOT NULL column with default value NULL: ALTER TABLE "employees" ADD "age" integer NOT NULL
🌐
Redgate Software
red-gate.com › home › learning & community › product learning › problems with adding not null columns or making nullable columns not null (ei028)
Problems with adding NOT NULL columns or making nullable columns NOT NULL (EI028) | Redgate
August 6, 2019 - Msg 515, Level 16, State 2, Line 58 Cannot insert the value NULL into column 'Word', table 'PhilFactor.dbo.CountingWords'; column does not allow nulls. UPDATE fails. The statement has been terminated. Listing 4: Failed attempt to make the Word column NOT NULL · Aiee! We still can’t make column non-nullable, even though we’ve told SQL Server what to insert for NULL columns! First, we must remove any existing NULLs explicitly, by updating all the rows with the default value:
Find elsewhere
Top answer
1 of 1
23

I'll share how I have done this in the past. It is designed to solve the specific limitation of pre-deployment scripts that you call out in your second point:

Adding the column in a pre-deployment script will fail the publish when it automatically tries to create the same column, a second time (even if the pre-deployment script is written to be idempotent)

Why pre-deployment scripts don't work for this

When you deploy an SSDT project, the way it stitches thing together is like this (a bit simplified, but in general):

  1. Do the "schema compare" between the source (dacpac file) and the target (database)
  2. Generate a deployment script based on the results of that compare
  3. Process any pre-deployment scripts in the dacpac (doing token replacement, etc.) and insert the contents into the beginning of the deployment script
  4. Do the same for post-deployment scripts, appending to the end of the deployment script

When a new column exists in the dacpac and not in the target database, step #2 will generate code to add that column. So if the pre-deployment script adds this column, the main part of the script will fail (because it assumes the column doesn't exist, based on the results of the schema compare in step #1)

Solution: pre-SSDT script

Martin Smith mentioned this option in a comment, and it's the solution that has worked best for me so far:

We use premodel scripts in our deplyment pipeline. This is not something that is part of SSDT but a step that runs before the dacfx publish. So in this case the premodel script could add the column with the desired values and make it not null and by the time the publish happens it is already in the state expected by SSDT so it doesnt have anything to do. I'm still yet to find much use for predeploy scripts. – Martin Smith

The steps to implement this solution in general are:

  1. Create a script in the SSDT project to hold your "pre-SSDT" T-SQL code
    • Depending on how your deployment process works, code in these files should probably be idempotent
  2. Make sure to set this script to "Build Action=None" and "Copy to Output Directory=Copy always" - the "copy always" option is especially important, as the deployment process needs to be able to find this script in your deployment artifacts
  3. In your deployment process, locate and run this script (or scripts) before the SSDT schema compare occurs
  4. Once that script has been executed successfully, you can engage DacServices / DacFx / whatever to complete your deployment as usual

In the end, this allows you to add the column using whatever custom code you like, populated using complex business logic, in the pre-SSDT script.

You also add the column definition in the SSDT project (so source control still matches the real life state of the database). But when the schema compare runs, it sees no changes related to that column (because you've already deployed it).

Other uses of pre-SSDT

I often find when testing deployments that SSDT performs a "table rebuild" operation* when it's completely unnecessary. This is where a new table is a created with the updated schema, all data is copied to that table, the old table is dropped, and the new table is renamed to replace the old table.

This can lead to massive transaction log file growth and other problems if the table is large. If I notice that a schema change is causing this, I'll instead make the change myself in pre-SSDT (which is usually a simple ALTER TABLE statement) and avoid the table rebuild.

Is this a good idea?

I think so. If you read Critiquing two different approaches to delivering databases: Migrations vs state by Alex Yates, this is essentially combining the two approaches a bit. SSDT is state based, but we incorporate a migration step (before SSDT) to handle some of the more complex scenarios that SSDT just has no way of dealing with in a general way.

In doing some searching while writing this answer, this is actually a very common approach discussed in the SSDT user community once you know what to search for. I've seen it called:

  • pre-compare
  • pre-model
  • pre-DAC
  • pre-SSDT

Etc. Here's a great article that covers a lot of the points that I mentioned above:

Pre-Compare & Pre-Deployment Scripts to SSDT

And one from Red Gate (in the #4 – Changing from system type to user defined type section) that also refers to this as pre-compare:

How to Fix Ten SSDT Deployment Snags, With or Without ReadyRoll

So what's the point of pre-deployment scripts?

Martin points out that he hasn't found "much use for predeploy scripts." I tend to feel the same way. But there are scenarios where they can be useful.

One example a coworker pointed out to me was storing some data in a temp table to be used in the post deployment script (say you're moving a column from one table to another).


*The table rebuild looks like this, which is horrifying, right?

GO
PRINT N'Starting rebuilding table [dbo].[MyTable]...';


GO
BEGIN TRANSACTION;

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET XACT_ABORT ON;

CREATE TABLE [dbo].[tmp_ms_xx_MyTable] (
    [Id] BIGINT IDENTITY (1, 1) NOT NULL,
    -- etc, other columns
);

IF EXISTS (SELECT TOP 1 1 
           FROM   [dbo].[MyTable])
    BEGIN
        SET IDENTITY_INSERT [dbo].[tmp_ms_xx_MyTable] ON;
        INSERT INTO [dbo].[tmp_ms_xx_MyTable] ([Id], ...)
        SELECT   [Id],
                 -- etc, other columns
        FROM     [dbo].[MyTable]
        ORDER BY [Id] ASC;
        SET IDENTITY_INSERT [dbo].[tmp_ms_xx_MyTable] OFF;
    END

DROP TABLE [dbo].[MyTable];

EXECUTE sp_rename N'[dbo].[tmp_ms_xx_MyTable]', N'MyTable';

COMMIT TRANSACTION;

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
🌐
Quora
quora.com › Can-I-add-NOT-NULL-constraint-after-table-creation
Can I add NOT NULL constraint after table creation? - Quora
Answer (1 of 7): Yes you can alter column definition by adding not null after table creation SQL SERVER : ALTER TABLE tablename ALTER COLUMN columnname datatype NOT NULL NOTE : Column must not contain any null value for above query to execute ...
🌐
Atlassian
atlassian.com › data › databases › how-to-alter-a-column-from-null-to-not-null-in-sql-server
How to alter a column from NULL to NOT NULL in SQL server
Changing the data structure of a column in SQL Server from NULL to NOT NULL, thereby disallowing non-null values in that column, is generally performed using the relatively simple ALTER TABLE syntax to appropriately change the column in question. In this tutorial we’ll examine the important safety precautions necessary when altering existing data in a column, prior to actually issuing any ALTER commands that would potentially cause harm to the table itself.
🌐
CastorDoc
castordoc.com › how-to › how-to-add-a-not-null-constraint-in-mysql
How to Add a NOT NULL Constraint in MySQL?
January 24, 2024 - The ALTER TABLE statement allows you to modify the structure of an existing table by adding, modifying, or removing columns and constraints. The ALTER TABLE command is used to add the NOT NULL constraint to a specific column in an existing table.
🌐
GeeksforGeeks
geeksforgeeks.org › sql › sql-not-null-constraint
SQL NOT NULL Constraint - GeeksforGeeks
February 10, 2026 - You can also add a NOT NULL constraint to an existing column in a table using the ALTER TABLE statement: ALTER TABLE table_name MODIFY column_name data_type(size) NOT NULL; Let's understand NOT NULL in SQL with examples.
🌐
OneUptime
oneuptime.com › home › blog › how to add a not null constraint in mysql
How to Add a NOT NULL Constraint in MySQL
3 weeks ago - NOT NULL alone: must provide a ... a NOT NULL constraint to an existing MySQL column, first check for and resolve any NULL values in that column, then use ALTER TABLE ......
🌐
Tutorialspoint
tutorialspoint.com › sql › sql-not-null-constraint.htm
SQL - NOT NULL Constraint
You can add or remove the NOT NULL constraint on an existing table using the ALTER TABLE statement. Adding this constraint ensures that a column cannot store NULL values, while removing it allows NULL values in that column.