SQL - How to ALTER COLUMN on a computed column - sql

I'm working with SQL Server 2008. Is it possible to alter a computed column without actually dropping the column and then adding it again (which I can get to work)? For example, I have this table:
CREATE TABLE [dbo].[Prices](
[Price] [numeric](8,3) NOT NULL,
[AdjPrice] AS [Price] / [AdjFactor],
[AdjFactor] [numeric](8,3) NOT NULL)
Later realizing that I have a potential divide by zero error I want to alter the [Adjprice] column to handle this, but if I just drop the column and add it again, I lose the column order.
I want to do something like:
ALTER TABLE dbo.[Prices]
ALTER COLUMN [AdjPrice] AS (CASE WHEN [AdjFactor] = 0 THEN 0 ELSE [Price] / [AdjFactor] END)
But this isn't correct. If this is possible, or there is another solution, I would appreciate the help.

Unfortunately, you cannot do this without dropping the column first.
From MSDN:
ALTER COLUMN
Specifies that the named column is to be changed or altered. ALTER COLUMN is not allowed if the compatibility level is 65 or lower. For more information, see sp_dbcmptlevel (Transact-SQL).
The modified column cannot be any one of the following:
A computed column or used in a computed column.

if you must maintain order, copy the data into a duplicate table, then rebuild the table to keep your column order, then copy the data from the duplicate table back in.
Just be sure to do this when there is no activity going on.

NO
if it is computed, what is the big deal dropping it and adding it again? is it PERSISTED and there are million of rows?

I do not think you can alter this column with out dropping.
So drop the colum then add new column.
If you find out any other way to do this please tell me.

its easy to overcome divide by zero error
use
SELECT
( 100 / NULLIF( 0, 0 ) ) AS value
it will return a null, if 0 is in that column,
instead of alter go for update by using the above example
Also read the 3rd normalization for computed column

Related

SQL Server: Add a column with calculated Field

I'm trying to alter a table to add an additional column that has the last 3 digits of org_id. I am doing this because software I am using cannot read 34000000000000000002 because of the size. I would like to turn 34000000000000000002 into 002 and put it in the new column. I thought something like below would work
alter table [org] add new_org_id integer value (select right(org_id,3));
I am very new at sql so I apologize if i'm not even close.
You were close. See the documentation for the correct syntax.
alter table [org] add new_org_id as right(org_id,3);
Also, you may want to make this a persisted computed column
PERSISTED Specifies that the Database Engine will physically store the
computed values in the table, and update the values when any other
columns on which the computed column depends are updated. Marking a
computed column as PERSISTED allows an index to be created on a
computed column that is deterministic, but not precise. For more
information, see Indexes on Computed Columns. Any computed columns
used as partitioning columns of a partitioned table must be explicitly
marked PERSISTED. computed_column_expression must be deterministic
when PERSISTED is specified.
Pretty close I think.
I'd do
alter table [org] add new_org_id integer
UPDATE [org]
SET new_org_id = right(org_id,3);

Efficiently add a column with a value

I am trying to add a column to a tsql table, i do this using SMO in c#. Altering the table is fine but i want to set the column to have a value. The table contains 650 million rows and the update query is taking over a day and a half to run.
Update [TempDatabase].[dbo].[table1] set RawSource = 'DTP'
This is the query I am running above.
Can anyone think of a more efficient way of doing this?
Thanks in advance.
Sometimes, it is more efficient to copy the table with the new value and re-create the table in a single command. Also, you might want to be sure that you have minimal logging for these operations.
Probably the best solution is to use a default value when you create the column:
alter table table1 add RawSource varchar(255) not null default 'DTP';
If you don't want the default moving forward, you can remove it after the column is added.
Another method uses computed columns, but basically does the same thing:
alter table table1 add _RawSource varchar(255);
alter table1 add RawSource as (coalesce(_RawSource, 'DTP'));
at the time of addition of column to table only we can set a default value which will applies for all rows
Note:U should keep not null compulsory because if not all rows are applicable with nulls
alter table table_name
add row_source nvarchar(5) not null default(N'DTP')

is there an easy to use formula for switching the datatype on a table column from int to bit?

I'm looking at a sql server table, and one of the columns seems to have been setup to be of type INT NULL when it's really better off as a BIT NOT NULL.
Is there an easy formula or shortcut for switching the type?
My current strategy is:
add new temp column
populate with data based on old column contents
drop old column and constraints
rename new column to old column name
add constraints based on new column
this seems complicated but, really, should be automatable - so i'm wondering if anyone's automated it yet.
Update MyTable set MyColumn = 0 where MyColumn is null
Assuming you want null to be false
Alter table MyTable alter column MyColumn bit not null
Will do the job, given all non-zero values are to be treated as true.
Course you were going to backup before you did any of this weren't you. :)

How best to sum 2 columns and update 3rd column with sum?

I am looking for the best way to add 2 or more columns in a SQL Server table and update another column with there sum.
Yes, I know this is a dumb thing to do and calculations should be done at time of transaction but I am modifying an existing table where the data in a column now needs to be more detailed but numerous processes will still use the column value.
For example, a column name is TotalDailyMiles and numerous processes access and use that field. Now more detail is needed. 2 columns need to be added to the table TotalAMMiles and TotalPMMiles. These 2 columns will sum to the existing column. Changing all the processes that access the TotalDailyMiles column to use the 2 new columns instead is not an option. The data for the new columns in old records does not exist so the value for columns holding the sum of the 2 new columns cannot be based on the 2 new columns in old records because in old records the new column values will be 0, or maybe null but I'm leaning toward 0 so I can set the new columns as Not Null.
I'm thinking of using a trigger to update the column holding the sum based on the new columns changing but I'm hoping one of you smart people have a better option.
How about treating the existing column as its own value (which will be 0 in future rows), adding the two new columns, and then creating a calculated column with the same name as the old Total? Something like this (I'm assuming a data type of decimal(7, 2) but of course use what you have, though I hope it's not float):
EXEC sp_rename 'dbo.Miles.TotalDailyMiles', 'DailyMiles';
ALTER TABLE dbo.Miles ADD COLUMN AMMiles decimal(7, 2) NOT NULL
CONSTRAINT DF_Miles_AMMiles DEFAULT (0);
ALTER TABLE dbo.Miles ADD COLUMN PMMiles decimal(7, 2) NOT NULL
CONSTRAINT DF_Miles_PMMiles DEFAULT (0);
ALTER TABLE dbo.Miles ADD COLUMN TotalDailyMiles
AS (DailyMiles + AMMiles + PMMiles) PERSISTED;
Some possible housekeeping that might be needed on the DailyMiles column, too:
-- if not already NOT NULL
ALTER TABLE dbo.Miles ALTER COLUMN AMMiles decimal(7, 2) NOT NULL;
-- if not already defaulting to 0
ALTER TABLE dbo.Miles ADD
CONSTRAINT DF_Miles_DailyMiles DEFAULT (0) FOR DailyMiles;
You could additionally add a constraint that either DailyMiles must be 0, or AMMiles and PMMiles must both be 0:
ALTER TABLE dbo.Miles ADD CONSTRAINT CK_Miles_DailyOrAMPM
CHECK (DailyMiles = 0 OR (AMMiles = 0 AND PMMiles = 0));
As long as consumers of the data don't try to update the TotalDailyMiles column, you've solved your problem handily.

How to insert columns in between in table in sql server 2008

I want to add or update columns using alter table if i am adding a new column i want show error. I am using the code below
alter table Personal_Details alter columns DOB datetime
if i uncheck the NULL to not NULL then it will shows column does not allow nulls; update fails;
i want to insert the fields in between columns not at end.
Plese fix my bug,
Thanks in advance.
The position of the column in the table declaration has nothing to do with its being NULL or NOT NULL.
If you are adding a column (of any type) which you want to be NOT NULL, i.e. you want to prohibit NULL values in that column, and the table already contains some rows, you must also provide some default value. For example:
ALTER TABLE Personal_Details
ADD COLUMN DOB datetime NOT NULL DEFAULT (GETDATE())
Otherwise the engine will attempt to add that column with NULLs as its values, which will violate the NOT NULL property, and the change, therefore, will be reverted.
Basically, the same applies when you want to set an existing column's NOT NULL property on while the column already contains NULLs. But in this case you must explicitly eliminate the NULLs before the change by either replacing them with values or removing the respective rows.
Source:
ALTER TABLE (Transact-SQL). (The particular section related to your problem is just above this code snippet.)
1)For ur adding column with not null problem
Use
ALTER TABLE Personal_Details ADD COLUMN DOB datetime NULL
Update the DOB column with the required dates and make sure there is no null in the column
then alter the column using
ALTER TABLE Personal_Details ALTER COLUMN DOB datetime not NULL
2)For your column going to the end problem...
you should not be worried...the order in which the columns are arranged doesnt matter...unless u are using a pathetic way of accessing data by column order..in which case again..u should stop accessing it by column order...
If the column order really matters you can change it using design option in the sql management table(rightclick on table >design and drag the column to its required place.)