I need to update 2 datetime columns, and I need them to be exactly the same, using mysql version 4.1.20. I'm using this query:
mysql> update table set last_update=now(), last_monitor=now() where id=1;
It is safe or there is a chance that the columns are update with different time, because of the 2 visible calls to now()?
I don't think that it can be update with different values (I think internally mysql calls now() just once per row or something similar), but I'm not an expert, what do you think?
Update:
Second question was extracted here.
Found a solution:
mysql> UPDATE table SET last_update=now(), last_monitor=last_update WHERE id=1;
I found this in MySQL Docs and after a few tests it works:
the following statement sets col2 to the current (updated) col1 value, not the original col1 value. The result is that col1 and col2
have the same value. This behavior differs from standard SQL.
UPDATE t1 SET col1 = col1 + 1, col2 = col1;
Mysql isn't very clever. When you want to use the same timestamp in multiple update or insert queries, you need to declare a variable.
When you use the now() function, the system will call the current timestamp every time you call it in another query.
MySQL evaluates now() once per statement when the statement commences execution. So it is safe to have multiple visible now() calls per statement.
select now(); select now(), sleep(10), now(); select now();
+---------------------+
| now() |
+---------------------+
| 2018-11-05 16:54:00 |
+---------------------+
1 row in set (0.00 sec)
+---------------------+-----------+---------------------+
| now() | sleep(10) | now() |
+---------------------+-----------+---------------------+
| 2018-11-05 16:54:00 | 0 | 2018-11-05 16:54:00 |
+---------------------+-----------+---------------------+
1 row in set (10.00 sec)
+---------------------+
| now() |
+---------------------+
| 2018-11-05 16:54:10 |
+---------------------+
1 row in set (0.00 sec)
You can store the value of a now() in a variable before running the update query and then use that variable to update both the fields last_update and last_monitor.
This will ensure the now() is executed only once and same value is updated on both columns you need.
You can put the following code on the default value of the timestamp column:
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, so on update the two columns take the same value.
If you really need to be sure that now() has the same value you can run two queries (that will answer to your second question too, in that case you are asking to update last_monitor = to last_update but last_update hasn't been updated yet)
you could do something like:
mysql> update table set last_update=now() where id=1;
mysql> update table set last_monitor = last_update where id=1;
anyway I think that mysql is clever enough to ask for now() only once per query.
There are 2 ways to this;
First, I would advice you declare now() as a variable before injecting it into the sql statement. Lets say;
var x = now();
mysql> UPDATE table SET last_update=$x, last_monitor=$x WHERE id=1;
Logically if you want a different input for last_monitor then you will add another variable like;
var y = time();
mysql> UPDATE table SET last_update=$x, last_monitor=$y WHERE id=1;
This way you can use the variables as many times as you can, not only in mysql statements but also in the server-side scripting-language(like PHP) you are using in your project.
Remember these same variables can be inserted as inputs in a form on the front-end of the application. That makes the project dynamic and not static.
Secondly if now() indicates time of update then using mysql you can decalre the property of the row as a timestamp. Every time a row is inserted or updated time is updated too.
Related
Actually i am using MySql 5.6.4 version.But the problem is that MySQL retrieves and displays TIME values in 'hh:mm:ss' format (or 'hhh:mm:ss' format for large hours values).
TIME values may range from '-838:59:59' to '838:59:59'. The hours part may be so large because the TIME type can be used not only to represent a time of day (which must be less than 24 hours), but also elapsed time or a time interval between two events (which may be much greater than 24 hours, or even negative).
I want to restrict TIME data type in mysql 5.6.4 version to hold only till 24:00:00 hrs, so if will insert the time which is greater than 24:00:00 then it will show error message.
I have googled a lot for this but i didn'yt find anything although i am bit confused... I just want to know How can i do it?
Insert into exp1.mock_table (reviewTime, created_dt) VALUES ('37:00:00', NOW());
Insert into exp1.mock_table (reviewTime, created_dt) VALUES ('22:01:53', NOW());
alter table exp1.mock_table modify reviewTime time(0) , add check (extract(hour from reviewTime) between 0 and 24);
If you are using MySQL 8+, then you may handle this using check constraints when you define your table:
CREATE TABLE mock_table (
reviewTime time CHECK (HOUR(time) < 24)
created_dt datetime
);
Technically a 24 hour day doesn't support 24:00:00, because 23:59:59 automatically wraps around to 00:00:00 of the next day.
Not sure if this is what #strawberry had in mind but you could test the time and force burst it
drop table if exists t;
create table t
(ts time);
insert into t values (if('20:00:00' > '23:59:59','840:00:00','20:00:00'));
Query OK, 1 row affected (0.02 sec)
insert into t values (if('37:00:00' > '23:59:59','840:00:00','820:00:00'));
ERROR 1292 (22007): Incorrect time value: '840:00:00' for column 'ts' at row 1
select * from t;
+----------+
| ts |
+----------+
| 20:00:00 |
+----------+
1 row in set (0.00 sec)
Consider the following:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table (id SERIAL PRIMARY KEY, t TIME NOT NULL);
INSERT INTO my_table (t) SELECT '22:23:00' FROM (SELECT 1) n WHERE TIME_TO_SEC('22:23:00') BETWEEN 0 AND 86400;
INSERT INTO my_table (t) SELECT '212:23:00' FROM (SELECT 1) n WHERE TIME_TO_SEC('212:23:00') BETWEEN 0 AND 86400;
SELECT * FROM my_table;
+----+----------+
| id | t |
+----+----------+
| 1 | 22:23:00 |
+----+----------+
How can I update only the time in an already existing DateTime field in MySQL? I want the date to stay the same.
Try this:
UPDATE yourtable
SET yourcolumn = concat(date(yourcolumn), ' 21:00:00')
WHERE Id = yourid;
Try this:
UPDATE t1 SET DateTimeField = CONCAT(DATE(DateTimeField),' 12:34:56');
UPDATE myTable
SET myDateTime = ADDTIME(DATE(myDateTime), #myTimeSpan)
WHERE id = #id;
Documented on MySQl date functions MySQL docs
I have solved in this way:
UPDATE table
SET myDateTime = CONCAT_WS(' ',DATE(myDateTime), CURTIME())
WHERE id = #id;
Obviously you should change CURTIME() with your desired time.
UPDATE myTable
SET myDateTime = ADDTIME(myDateTime, #myTimeSpan)
WHERE id = #id;
For exact syntax of function, see this.
Try this:
UPDATE sms
SET entry_period_end_date= entry_period_end_date+INTERVAL 6 Hour
WHERE TIME(entry_period_end_date) = '06:00:00';
UPDATE `table`
SET time = ADDTIME(time, INTERVAL 13 Hour);
Well, exactly what you are asking for is not possible. The date and time components can't be updated separately, so you have to calculate the new DateTime value from the existing one so that you can replace the whole value.
MySQL DEV page shows functions like subtime and difftime
A sample code to back the time all posts in 3 hours is above:
UPDATE tablepost SET datepost = SUBTIME( datepost , '0 3:0:0' );
Note that values 0 dont alter the respective field. Take care this code, use select first to test these function.
Reference: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_subtime
Asuming you have a DATE field and TIME field and want to inject the time into the date, try this:
UPDATE mytable
SET mydatefield = ADDTIME( DATE_FORMAT(mydatefield,'%Y-%m-%d 00:00:00'), mydatefield)
WHERE myid = ...
I used ADDTIME in the following way
Earlier in my cloud server, the DateTime was set to UTC but after changing the DateTime to Asia/Kolkata ie UTC 5:30 I wanted the same to reflect in my database tables.
I wanted to update the created_at and updated_at column by 5 hours 30 minutes. I did the following
To update all the rows of the table
UPDATE
products
SET
created_at = ADDTIME(created_at, '5:30:0'),
updated_at = ADDTIME(updated_at, '5:30:0')
You can omit the WHERE condition if you want to update all the records, but since my new records were updated with proper values. So only my rows below id less than 2500 must be updated
UPDATE
products
SET
created_at = ADDTIME(created_at, '5:30:0'),
updated_at = ADDTIME(updated_at, '5:30:0')
WHERE
id < 2500;
This what helped me. I convert time to minutes firstly: 150 for 2:30 am.
UPDATE lesson SET starts_at = DATE_ADD(Date(starts_at), INTERVAL 150 MINUTE)
Minutes are enough accurate for me, though you can use other units: https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-add
I have a MySQL database, which I cannot alter, where I read date from. The issue is that I have a varchar column that stores a date. The date is stored in the atomtime format eg. 2014-06-01T00:00:00+02:00.
I cannot figure how to specify the format in the STR_TO_DATE function. I tried STR_TO_DATE(Endtime, '%Y-%m-%dT%H:%i:%s+02:00'), but that doesn't work.
Do anyone have a solution for this?
I am trying to run the following query (which is not working properly):
SELECT *, COUNT(*) as antal
FROM ivocall_calls
WHERE Agentname LIKE 'Vinh Nguyen'
AND Status1 = 'SALG'
AND STR_TO_DATE(Endtime, '%Y-%m-%dT%H:%i:%s+02:00')
BETWEEN STR_TO_DATE('2014-06-01T00:00:00+02:00', '%Y-%m-%dT%H:%i:%s+02:00')
AND STR_TO_DATE('2014-06-30T00:00:00+02:00', '%Y-%m-%dT%H:%i:%s+02:00')
Thanks in advance.
This is probably best-addressed using a stored function to parse and convert the timestamps from the stored format into MySQL's native format, using the built-in date time math functions to do the time zone conversions.
The function below will correctly handle two formats, YYYY-MM-DDTHH:MM:SSZ and YYYY-MM-DDTHH:MM:SS+/-HH:MM as well as correctly formed MySQL datetime literals, which will be passed through unmodified.
DELIMITER $$
DROP FUNCTION IF EXISTS `from_iso8601_subset` $$
CREATE FUNCTION `from_iso8601_subset`(in_ts TINYTEXT) RETURNS DATETIME
DETERMINISTIC
NO SQL
BEGIN
-- this function takes an input timestamp value in a suppported subset of iso8601 values, and
-- and converts it to the equivalent MySQL datetime value, expressed in the current session's
-- time zone. Since this is also the timezone that columns in the TIMESTAMP data type expect,
-- this causes the input value to be stored correctly in the native TIMESTAMP format, which is.
-- UTC under the hood.
-- if you are taking the value here and stuffing it into a DATETIME column, you need to have your
-- session ##time_zone set to the same zone in which that column should be stored, or use
-- CONVERT(from_iso('input value'),'UTC','Your Desired Time Zone');
-- 2014-02-01T23:59:59Z --
IF (in_ts REGEXP '^[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}[T ][[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}(Z|[+-][[:digit:]]{2}:[[:digit:]]{2})$') THEN
SET in_ts = REPLACE(REPLACE(in_ts, 'T', ' '), 'Z', '+00:00');
RETURN CONVERT_TZ(SUBSTRING(in_ts FROM 1 FOR 19), SUBSTRING(in_ts FROM 20 FOR 24), ##time_zone);
-- unexpected format -- let MySQL's built-in functions do the best they can; this will throw warnings
-- if the input is not a yyyy-mm-dd hh:mm:ss datetime literal; alternately this could return NULL.
ELSE
RETURN CAST(in_ts AS DATETIME);
END IF;
END $$
DELIMITER ;
Example output:
mysql> SET ##time_zone = 'America/New_York';
Query OK, 0 rows affected (0.08 sec)
mysql> SELECT from_iso8601_subset('2014-06-01T00:00:00+02:00');
+--------------------------------------------------+
| from_iso8601_subset('2014-06-01T00:00:00+02:00') |
+--------------------------------------------------+
| 2014-05-31 18:00:00 |
+--------------------------------------------------+
1 row in set (0.08 sec)
mysql> set ##time_zone = 'UTC';
Query OK, 0 rows affected (0.08 sec)
mysql> SELECT from_iso8601_subset('2014-06-01T00:00:00+02:00');
+--------------------------------------------------+
| from_iso8601_subset('2014-06-01T00:00:00+02:00') |
+--------------------------------------------------+
| 2014-05-31 22:00:00 |
+--------------------------------------------------+
1 row in set (0.08 sec)
We assume that if the input data matches one of the patterns, then the contents of the value passed in are also going to be sane; if you give nonsense input values, you'll get some nonsense output, such as if you are using a time zone of '+99:00' but it won't fail. This function does not have any SQL injection vulnerabilities.
The code could be further-optimized, but as written, this function is efficient enough that it can evaluate several thousand expressions per second on a moderately-powered machine.
Use unix_timestamp() instead:
SELECT something, COUNT() as antal FROM ivocall_calls
WHERE Agentname LIKE 'Vinh Nguyen'
AND Status1 = 'SALG'
AND unix_timestamp(Endtime) BETWEEN
unix_timestamp('2014-06-01T00:00:00+02:00' and unix_timestamp('2014-06-30T00:00:00+02:00');
Im trying to figure out a way to fix a database schema issue.
In column 1 a y-m-d H:i:s date is stored (timestamp field)
col1 = 2009-11-12 00:00:00
In column 2 a time is stored (varchar)
col2 = 15:48
I'm thinking that storing it in one column would be more efficient than separately, so I'm trying to make column 3 a datetime field
col3 = 2009-11-12 15:48:00
Unless keeping it original is fine.
Yes, definitely use one field, you can get just the date or time from it later if you need. I believe you can run the following query to update col3 with the correct datetimes.
UPDATE tablename
SET col3 = CAST(LEFT(col1, 10) + " " + col2 + ":00", DATETIME)
If you don't have anything accessing these old fields (col1 and col2), you should get rid of them for clarity. If you do, it is going to be tricky decided whether or not to maintain two fields for the same data.
Addtime should do what you need
mysql> select addtime('2012-05-05 00:00:00', '11:12');
+-----------------------------------------+
| addtime('2012-05-05 00:00:00', '11:12') |
+-----------------------------------------+
| 2012-05-05 11:12:00 |
+-----------------------------------------+
1 row in set (0.00 sec)
Contrary to the other answers... I wouldn't immediately suggest combining these columns.
Consider how the columns are going to be queried - in my experience, efficient queries are more important than disk space efficiency - as such, if you're want to select rows based on date (ignoring time) and/or time (ignoring date) you would want these in separate columns. Whilst you can get the date from a datetime column, if you have lots of rows, doing that on each row before running a query would be really inefficient. (For example... consider this SO question)
Not sure really where to start with this one. Can anyone help/point me in the right direction.
I have a timestamp column in MySQL and I want to select a date range for example, all timestamps which are in Oct 2010.
Thanks.
Usually it would be this:
SELECT *
FROM yourtable
WHERE yourtimetimefield>='2010-10-01'
AND yourtimetimefield< '2010-11-01'
But because you have a unix timestamps, you'll need something like this:
SELECT *
FROM yourtable
WHERE yourtimetimefield>=unix_timestamp('2010-10-01')
AND yourtimetimefield< unix_timestamp('2010-11-01')
A compact, flexible method for timestamps without fractional seconds would be:
SELECT * FROM table_name
WHERE field_name
BETWEEN UNIX_TIMESTAMP('2010-10-01') AND UNIX_TIMESTAMP('2010-10-31 23:59:59')
If you are using fractional seconds and a recent version of MySQL then you would be better to take the approach of using the >= and < operators as per Wouter's answer.
Here is an example of temporal fields defined with fractional second precision (maximum precision in use):
mysql> create table time_info (t_time time(6), t_datetime datetime(6), t_timestamp timestamp(6), t_short timestamp null);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into time_info set t_time = curtime(6), t_datetime = now(6), t_short = t_datetime;
Query OK, 1 row affected (0.01 sec)
mysql> select * from time_info;
+-----------------+----------------------------+----------------------------+---------------------+
| 22:05:34.378453 | 2016-01-11 22:05:34.378453 | 2016-01-11 22:05:34.378453 | 2016-01-11 22:05:34 |
+-----------------+----------------------------+----------------------------+---------------------+
1 row in set (0.00 sec)
I can see people giving lots of comments on this question. But I think, simple use of LIKE could be easier to get the data from the table.
SELECT * FROM table WHERE COLUMN LIKE '2013-05-11%'
Use LIKE and post data wild character search. Hopefully this will solve your problem.
SELECT * FROM table WHERE col >= '2010-10-01' AND col <= '2010-10-31'
This SQL query will extract the data for you. It is easy and fast.
SELECT *
FROM table_name
WHERE extract( YEAR_MONTH from timestamp)="201010";
Whenever possible, avoid applying functions to a column in the where clause:
SELECT *
FROM table_name
WHERE timestamp >= UNIX_TIMESTAMP('2010-10-01 00:00:00')
AND timestamp < UNIX_TIMESTAMP('2010-11-01 00:00:00');
Applying a function to the timestamp column (e.g., FROM_UNIXTIME(timestamp) = ...) makes indexing much harder.
If you have a mysql timestamp, something like 2013-09-29 22:27:10 you can do this
select * from table WHERE MONTH(FROM_UNIXTIME(UNIX_TIMESTAMP(time)))=9;
Convert to unix, then use the unix time functions to extract the month, in this case 9 for september.