Efficiently add a column with a value - sql

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

Related

Deleting entire data from a particular column in oracle-sql

Recently I have started learning Oracle-sql. I know that with the help of DELETE command we can delete a particular row(s). So, Is it possible to delete entire data from a particular column in a table using only DELETE command. (I know that using UPDATE command by setting null values to entire column we can achieve the functionality of DELETE).
DELETE
The DELETE statement removes entire rows of data from a specified
table or view
If you want to "remove" data from particular column update it:
UPDATE table_name
SET your_column_name = NULL;
or if column is NOT NULL
UPDATE table_name
SET your_column_name = <value_indicating_removed_data>;
You can also remove entire column using DDL:
ALTER TABLE table_name DROP COLUMN column_name;
In SQL, delete deletes rows not columns.
You have three options in Oracle:
Set all the values to NULL using update.
Remove the column from the table.
Set the column to unused.
The last two use alter table:
alter table t drop column col;
alter table t set unused (col);
Use Invisible Type, which is from an oracle 12cR2.
ALTER TABLE LOG1
MODIFY operation INVISIBLE
It is a better than drop of a particular column.If you need to visible you can get back by altering with an VISIBLE of a column name.
update employee set commission=nvl2(commission,'','')
this will remove all the data from the column

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

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

Is there an easy way to add a custom migration script to SQL Compare scripts?

At my work we are currently having some serious pains pushing our database changes across environments. The issue starts to show up when we create a new non-nullable column on an existing table. The script that SQL Compare generates creates the column as non-nullable, so it will always fail. I was hoping that there was some alternative to having to manually edit the script. Is there any way to get around this? If not, how do you guys handle it?
Create a table:
create table #bingo ( id int )
Add a value:
insert into #bingo values (1)
Add a new column:
alter table #bingo add userid int
Populate the new column:
update #bingo set userid = 1 where id = 1
Change the new column to not nullable:
alter table #bingo alter column userid int not null
You would have to manually edit the RedGate Sql Compare to make it work like this.
How do you plan on filling the NOT NULL column? I don't see how SQL Compare could really come up with a solution since it has no way of knowing how you would fill it.
You could create the column with a DEFAULT, then simply add an update statement at the end of the generated scripts to properly update the column if you have some source for the values.
add a default onto the new not null column
when creating a new not null column, what value do all the existing rows get? If you don't know, make the column nullable.

Change each record in a table with no primary key?

I have a table in a database that represents dates textually (i.e. "2008-11-09") and I would like to replace them with the UNIX timestamp. However, I don't think that MySQL is capable of doing the conversion on its own, so I'd like to write a little script to do the conversion. The way I can think to do it involves getting all the records in the table, iterating through them, and updating the database records. However, with no primary key, I can't easily get the exact record I need to update.
Is there a way to get MySQL to assign temporary IDs to records during a SELECT so that I refer back to them when doing UPDATEs?
Does this not do it?
UPDATE
MyTable
SET
MyTimeStamp = UNIX_TIMESTAMP(MyDateTime);
If for some reason you do have to iterate (the other answers cover the situation where you don't), I can think of two ways to do it (these aren't MySQL-specific):
Add a column to the table that's an auto-assigned number. Use that as the PK for your updates, then drop the column afterwards (or just keep it around for future use).
In a table with no defined PK, as long as there are no exact duplicate rows, you can use the entire row as a composite PK; just use every column in the row as your distinguishing characteristic. i.e., if the table has 3 columns, "name", "address", and "updated", do the following:
UPDATE mytable SET updated = [timestamp value] WHERE name = [name] AND address = [address] AND timestamp = [old timestamp]
Many data access frameworks use this exact strategy to implement optimistic concurrency.
No, you should be able to do this with a single update statement. If all of the dates are yyyy-mm-dd and they are just stored in some sort of text column instead of DATETIME, you can just move the data over. SQL would be like:
ALTER TABLE t ADD COLUMN dates DATETIME;
UPDATE t set t.dates=t.olddate;
This shouldn't be dependent on a PK because MySQL can scan through each row in the table. The only time PK's become an issue is if you need to update a single row, but the row may not be unique.
You can generate values during a SELECT using the MySQL user variables feature, but these values do not refer to the row; they're temporary parts of the result set only. You can't use them in UPDATE statements.
SET #v := 0;
SELECT #v:=#v+1, * FROM mytable;
Here's how I'd solve the problem. You're going to have to create another column for your UNIX timestamps anyway, so you can add it first. Then convert the values in the old datetime column to the UNIX timestamp and place it in the new column. Then drop the old textual datetime column.
ALTER TABLE mytable ADD COLUMN unix_timestamp INT UNSIGNED NOT NULL DEFAULT 0;
UPDATE mytable
SET unix_timestamp = UNIX_TIMESTAMP( STR_TO_DATE( text_timestamp, '%Y-%m-%d' ) );
ALTER TABLE mytable DROP COLUMN text_timestamp;
Of course you should confirm that the conversion has been done correctly before you drop the old column!
See UNIX_TIMESTAMP() and STR_TO_DATE()