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

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.

Related

Oracle will corrupt other column's data after DROP COLUMN [duplicate]

This question already has answers here:
Why does this Oracle DROP COLUMN alter the default value of another column?
(1 answer)
Oracle bug when adding not nullable columns with default
(2 answers)
Closed 1 year ago.
I have a table with some other columns and preexisting data in my development database. I need to add four more columns to store data for a new feature.
I've added four new columns to this table with the following commands:
alter table my_table add (pin_validacao_cadastro varchar2(6 char) default '000000' not null);
alter table my_table add (tentativas_validacao_pin number default 0 not null);
alter table my_table add (codigo_bloqueio number default 1 not null check (codigo_bloqueio in (0, 1, 2)));
alter table my_table add data_validacao_cadastro date;
Then, I've discovered that the first definition needed to change because the default value should be another value. Then, I've dropped the first column (pin_validacao_cadastro).
alter table my_table drop column pin_validacao_cadastro;
Suprisingly enough, before I try to recreate the first column with the correct default value, I've noticed the second column (tentativas_validacao_pin) now is altered and all the values are NULL, when it should to be 0.
Then, I've dropped the second column (tentativas_validacao_pin) to recreate it and fix the corruption.
alter table my_table drop column tentativas_validacao_pin;
But wait! Before I've had the chance to recreate it, I've noticed that all values of the third column (codigo_bloqueio) are equal to 0. Before the DROP command, all values of this column were equal to 1 (the default value for this column).
What am I missing here? Is this supposed to happen? It seems that the default value of the dropped column is being applyed to the next existing column.
Since the problem ocurrs using diferent database tools (sqldeveloper, sqlplus, PlSqldeveloper) I think that it is something related to oracle database.
Can anyone explain what is happening?
I'm using Oracle 11G.

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')

populate a column with a value based on value of other column alter table sql

I have a table 'Data' with a column 'Date'
I need to add another column called flag and populate it with 0 if the date is less than 2 years from current date and populate it with 1 if the date is more than 2 years from current date.
I did it by adding column using alter table and using update set statement as below
alter table data add flag INTEGER constraint flag_value check (flag in(0,1));
Is there a way to do this using just one alter table statement without using update set?
Is there a way to do this using just one alter table statement without using update set?
Not in sqlite, which does not support computed columns and there is no way to run a default UPDATE via an ALTER TABLE statement.
You could use the view approach from the linked question, or do as you've done and issue separate ALTER TABLE and UPDATE statements.

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.)

SQL - How to ALTER COLUMN on a computed column

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