I need a fast way duplicate a DATETIME column in a table and give it a new name.
I have a column named myDate in my table called myResults, I need a query to make a new column in the table called newDate which has the exact same data as the myDate column.
Is there a faster way to do this than by doing the obvious 2 step approach of make a new column, and then copying all the data (it's a large table and I'm looking for the fastest approach)?
Obvious solution:
ALTER TABLE `myResults` ADD `newDate` DATETIME;
UPDATE `myResults` SET `newDate` = `myDate`;
UPDATE `table_name` SET `new_column` = `existing_column` WHERE `id`=`id`
The obvious solution is the only solution, unfortunately.
However note that in general you shouldn't be copying a column in relational databases.
If you just need a default in there, you can either choose what the default is statically or use a function call.
ALTER TABLE `myResults` ADD `newDate` DATETIME DEFAULT '2010-01-01';
or
ALTER TABLE `myResults` ADD `newDate` DATETIME DEFAULT current_timestamp;
Why would your workload ever demand a new datetime column, that duplicates another columns data? This sounds like horrable practice? How about telling us what you're trying to achieve? You can pull a second column with the same data in a few different ways, without actually duplicating the data:
SELECT date1 AS date_old, date1 AS date_new FROM table;
-or-, you can create a view
CREATE VIEW virtual_table AS
SELECT date1 AS date_old, date1 AS date_new FROM table
;
SELECT * FROM virtual_table;
Related
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')
I would like to be able to add columns to a table with cells who's values are computed by need at 'querytime' when (possibly) selecting over them.
Are there some established ways of doing this?
EDIT: Okay I can do without the 'add columns'. What I want is to make a select query which searches some (if they exist) rows with all needed values computed (some function) and also fills in some of the rows which does not have all needed values computed. So each query would do it's part in extending the data a bit.
(Some columns would start out as null values or similar)
I guess I'll do the extending part first and the query after
You use select expression, especially if you don't plan to store the calculation results, or they are dependant on more than one table. An example, as simple as it could be:
SELECT id, (id+1) as next_id FROM table;
What type of database are you asking for? If it is SQL Server then you can use the computed columns by using the AS syntax.
Eg:
create table Test
(
Id int identity(1,1),
col1 varchar(2) default 'NO',
col2 as col1 + ' - Why?'
)
go
insert into Test
default values
go
select * from Test
drop table Test
In the SQL world it's usually expensive to add a column to an existing table so I'd advise against it. Maybe you can manage with something like this:
SELECT OrderID,
ProductID,
UnitPrice*Quantity AS "Regular Price",
UnitPrice*Quantity-UnitPrice*Quantity*Discount AS "Price After Discount"
FROM order_details;
If you really insist on adding a new column, you could go for something like (not tested):
ALTER TABLE order_details ADD column_name datatype
UPDATE order_details SET column_name = UnitPrice+1
You basically ALTER TABLE to add the new column, then perform an UPDATE operation on all the table to set the value of the newly added column.
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. :)
Hi all wonder if someone could advise a more efficient way to select rows from a table that has roughly 60 millions records in it. Each row has a date stored as a nvarchar, for example '20110527030000.106'. I want to select all rows that are 3 months or older based on this date field, so for example i'm only interested in the first part of the date field; '20110527'. I have the following code to do that, however its a bit slow and wondering if there was a better way?
DECLARE #tempDate varchar(12)
SET #tempDate = convert(varchar(12),DATEADD(m,-3,GETDATE()),112)
SELECT *
FROM [TABLE A]
WHERE SUBSTRING([DATE_FIELD],0,8) < #tempDate
Your query not only it can't use any index on [DATE_FIELD] and does a full scan but it also applies the SUBSTRING() function to all values of the (date_field column of the) table.
Don't apply any function on the column so the index of [DATE_FIELD] can be used and the function is only applied once, at the calculation of #tempDate :
SELECT *
FROM [TABLE A]
WHERE [DATE_FIELD] < #tempDate
The < comparison works for varchar values. The following will evaluate to True:
'20110526030000.106' < '20110527'
Is there any reason that the datetime is not stored as datetime type?
If you can modify the table you could add a datetime column and then run an update to populate it with the correct data.
If you can't modify the table then you could create a new table with a datetime column, extract the keys from the table you want to query into it and enforce a foriegn key contraint across the tables. Then you can popluate the datetime column as before and then join the tables when querying.
If you can't modify anything then I guess yiou could try benchmarking your solution against a solution where you cast the varchar date into a datetime on the fly (with a user defined function for example). This may actually run faster.
Hope this helps you some..
If you can modify the database you could add a new field isolder3months and set it to 1 for each new entry.
With triggers you can update that once a day for every entry with isolder3months = 1. This way you check / update only 1/n th of your entries.
This solution is only practical if 3 months is fix and if this query is used often.
Then your query would look like
SELECT *
FROM [TABLE A]
WHERE [isolder3months] = 1
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()