Best way to add a new column with an initial (but not default) value? - sql

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.

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.

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

Another, maybe more native, way would be:
ALTER TABLE tbl ADD COLUMN col INTEGER NOT NULL DEFAULT 1;
ALTER TABLE tbl ALTER COLUMN col DROP DEFAULT;
I'm not sure how long this function exists, but the PostgreSQL documentation goes back to version 7.1 and for 7.1 it is already described.

You can do it in an insert trigger

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.

Related

How to create a surrogate key column in existing table?

I would like to create a new column called PurchaseOrderID in an existing table using SSMS. It combines LineNumber and PONUMBER to create a surrogate key and then I would enter into table design mode and assign it a PK there.
Creating new column:
ALTER TABLE FactPurchaseOrders
ADD PurchaseOrderID VARCHAR(64);
Populating with values:
UPDATE FactPurchaseOrders
SET PurchaseOrderID = (CONVERT(VARCHAR(64), LineNumber) + CONVERT(VARCHAR(64), PONUMBER))
WHERE 1=1;
Currently with this I am unable to assign this column a PK and I believe because it is nullable.
I have also tried creating it in design mode first and the same problem occurs.
That is most certainly the case. After you have run your update, simply alter the columns you will use in your PK to NOT NULL. Since the columns will have values now it can be set as NOT NULL and then it will allow the assignment of PK. Also make sure there isn't already another PK on the table already. There can be only 1!
Update Records
Alter columns to not null
Create PK on fields

PostgreSQL column type conversion from bigint to bigserial

When I try to change the data type of a column in a table by alter command...
alter table temp alter column id type bigserial;
I get
ERROR: type "bigserial" does not exist
How can I change the datatype from bigint to bigserial?
As explained in the documentation, SERIAL is not a datatype, but a shortcut for a collection of other commands.
So while you can't change it simply by altering the type, you can achieve the same effect by running these other commands yourself:
CREATE SEQUENCE temp_id_seq;
ALTER TABLE temp ALTER COLUMN id SET NOT NULL;
ALTER TABLE temp ALTER COLUMN id SET DEFAULT nextval('temp_id_seq');
ALTER SEQUENCE temp_id_seq OWNED BY temp.id;
Altering the owner will ensure that the sequence is removed if the table/column is dropped. It will also give you the expected behaviour in the pg_get_serial_sequence() function.
Sticking to the tablename_columnname_seq naming convention is necessary to convince some tools like pgAdmin to report this column type as BIGSERIAL. Note that psql and pg_dump will always show the underlying definition, even if the column was initially declared as a SERIAL type.
As of Postgres 10, you also have the option of using an SQL standard identity column, which handles all of this invisibly, and which you can easily add to an existing table:
ALTER TABLE temp ALTER COLUMN id
ADD GENERATED BY DEFAULT AS IDENTITY
ALTERing a column from BIGINTEGER to BIGSERIAL in order to make it auto-increment won't work. BIGSERIAL is not a true type, it is a trick that automates PK and SEQUENCE creation.
Instead you can create a sequence yourself, then assign it as the default for a column:
CREATE SEQUENCE "YOURSCHEMA"."SEQNAME";
ALTER TABLE "YOURSCHEMA"."TABLENAME"
ALTER COLUMN "COLUMNNAME" SET DEFAULT nextval('"YOURSCHEMA"."SEQNAME"'::regclass);
ALTER TABLE "YOURSCHEMA"."TABLENAME" ADD CONSTRAINT pk PRIMARY KEY ("COLUMNNAME");
This is a simple workaround:
ALTER TABLE table_name drop column column_name, add column column_name bigserial;
Sounds like alot of professionals out there on this subject... if the original table did indeed have data then the real answer to this dilemma is to have designed the db correctly in the first place. However, that being the case, to change the column rule (type) would require integrity verification of that column for the new paradigm. And, don't forget, anywhere where that column is manipulated (added/updated) then that would need to be looked into.
If it's a new table then okay, simples: delete column and re-add new column (takes care of the sequence for you). Again, design, design, design.
I think we've all fouled on this.

SQL Server : trying to add non-null column to an existing table (table is empty)

I'm trying to add a new column to my exiting table but I keep getting an error trying to insert non-null columns.
I understand how this would be an issue to existing databases with lots of data, but my database has no data yet so I'm confused as to why I'm getting this error.
Is there an easy solution for this (I don't want to add default values)
You've got two options, feed it a default value, or add the field without the non-null constraint, then alter the table later to add the non-null constraint after you've populated the field.
This works fine when the table is empty.
CREATE TABLE X(Y INT)
ALTER TABLE T ADD Y INT NOT NULL
There is no need to add a temporary default constraint or create it as NULL, populate then ALTER except if the table is, in fact, not empty as claimed.
I don't think that table is as empty as you think it is.
Try this:
Truncate Table <YourTableName>
Then try the alter table statement.

How to add unique column in sybase?

I have a sybase db table in which i need to add a new column.
The conditions: The column must not allow nulls and be unique.
what is the alter table sql to achieve this?
EDIT:
It is a varchar type column.Yes the table as of now is empty, but when filled it is ensured that unique values would be filled in.
I tired executing
alter table Test add Name varchar not null unique
i get error saying default value must be specified as not null is given.
but i want to add unique constraint so do i really need to specify default?
thanks
Unique values are specified as part of an index on the column, not in the column definition itself.
Try:
alter table Test add Name varchar not null
create unique index index_name_unique on Test (Name)
The ASE reference manual can help with more detail.
Once a table has been created Sybase ASE does not allow addition of NOT NULL column directly unless a default is specified for the column. However, if the table is still empty you can do the following -
First add the new column as a NULL column to the table using alter table command -
alter table Test add Name varchar(100) null
Once this has been done, try modifying the same column Name in the table Test using the alter table script -
alter table Test modify Name varchar(100) NOT NULL
and you will see that you are able to modify the Name column to a NOT NULL column using these steps. This is because at this time Sybase server checks as there is no data in the table hence the NOT NULL constraint is not checked and the column is made NOT NULL. Hence, we are able to skip the default constraint.
In case there would have been some data already present in the table Test, then we need to add one more step in between steps 1 and 2 which will add default values to the existing rows in the table. This can be done via a script for previous data and then following the step 2.
To make the column only allow unique values for the column you need to add a unique key constraint using the following syntax -
alter table Test add constraint UK1 unique(Name)

SQL: Create new column with default, unique value

I have added a new column, called Ordinal, to a table called Activity. The problem is that I gave it a UNIQUE constraint, set it to allow NULL (though this I won't want in the end.. I just needed to set it to that to get a little farther with the script), and did not give it a default value. I'm now running a RedGate SQL Compare script that was generated by comparing this table to a version of the Activity table that does not have the column. But I'm getting the following error:
The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'iwt.Activity' and the index name 'IX_Activity'. The duplicate key value is (1).
So based on my research, it's trying to create a unique key constraint on the Ordinal column, but NULL is not unique. So my next step was to give it a unique value of 1 just to let the script pass. But 1 isn't going to be unique either. So, finally, my question:
Preferably in SQL Server Management Studio, how do I set a column as having a unique default value? Isn't that what I would need to create this constraint?
Thanks.
try this:
NULL will be the first constraint when you create the column.
UNIQUE will be as add constraint, you should add the second constraint.
they can run on this order with no problem (tested):
--first constraint
alter table Table_Name
add Column_Name int null
--second constraint
alter table Table_Name
add constraint Constraint_Name unique (Column_Name)
In my example :
PaymentGatewayHash is column
Cart is a table
--first query
alter table Cart
add PaymentGatewayHash NVARCHAR(20) null
--second query
CREATE UNIQUE INDEX PaymentGatewayHashUnique
ON Cart (PaymentGatewayHash)
WHERE PaymentGatewayHash IS NOT NULL
I just tested that :D