views:

402

answers:

4

I need to add a new column to a MS SQL 2005 database with an initial value. However, I do NOT want to automatically create a default constraint on this column. At the point in time that I add the column the default/initial value is correct, but this can change over time. So, future access to the table MUST specify a value instead of accepting a default.

The best I could come up with is:

ALTER TABLE tbl ADD col INTEGER NULL
UPDATE tbl SET col = 1
ALTER TABLE tbl ALTER COLUMN col INTEGER NOT NULL

This seems a bit inefficient for largish tables (100,000 to 1,000,000 records).

I have experimented with adding the column with a default and then deleting the default constraint. However, I don't know what the name of the default constraint is and would rather not access sysobjects and put in database specific knowledge.

Please, there must be a better way.

+2  A: 

You can do it in an insert trigger

Hans Malherbe
thats exactly what i think. btw y do you don't want to do it as constraint
Ratnesh Maurya
The question is for adding a column to a table with existing rows. Adding a trigger will only affect new rows. Am I missing something?
Dave Bauman
I think I misunderstood the question. When you say you want to add a column with an initial value, do you mean that you want to have all existing rows have this value without having to update them? In this case, you could add two columns. One is a nullable column and the other is a computed column. The computed column will return the default value if the other column is null, otherwise it will return the other column.This is a lot of complexity going forward. I would do rather do it like you did in your example.
Hans Malherbe
+3  A: 

I'd ALTER TABLE tbl ADD col INTEGER CONSTRAINT tempname DEFAULT 1 first,, and drop the explicitly named constraint after (presumably within a transaction).

Alex Martelli
+1. --- @Alex: I am not sure that one can do DDL within a trasactions.--- @Adrian: do you really care for it being inefficient? You are not doing it every day, are you? Usually I use the way you describe for clarity.
van
@van, I'm not 100% sure of the limitations of SqlServer'05 in this regard -- PostgreSQL does let you do alter table transactionally (with explicit BEGIN and COMMIT of the transaction, at least). To check if MS also does, SELECT @@TRANCOUNT should tell you (I can't find it clearly spelled out in the docs).
Alex Martelli
Shannon Severance
A: 

If you add a default constraint when creating the table, you won't know what it is called. However, if you add a constraint with ALTER TABLE, you must name the constraint. In this case, you would be able to ALTER TABLE DROP CONSTRAINT (This applies to T-SQL, not sure about other databases.)

However, this would require you to CREATE TABLE with NULL column, ALTER TABLE to add the constraint, make the column NOT NULL, and finally DROP CONSTRAINT.

I don't believe an insert trigger would work as someone else mentioned, because your rows are already added.

I think the way you describe may, in fact, be the most efficient and elegant solution.

Dave Bauman
+1  A: 

To add the column with a default and then delete the default, you can name the default:

ALTER TABLE tbl ADD col INTEGER NOT NULL CONSTRAINT tbl_temp_default DEFAULT 1
ALTER TABLE tbl drop constraint tbl_temp_default

This filled in the value 1, but leaves the table without a default. Using SQL Server 2008, I ran this and your code, of alter update alter and did not see any noticeable difference on a table of 100,000 small rows. SSMS would not show me the query plans for the alter table statements, so I was not able to compare the resources used between the two methods.

Shannon Severance