TimeZone not set correctly - php

I have a problem, I'm using mysql with PHP and I have in my database timestamp columns that are automatically set on update by the current timestamp. But when I'm trying to insert rows into the table the rows are added with timestamp different from my current time (before two hours) I have the EST timezone.
I've checked the timezone for the database and it is System and when I searched for that I read that it depeneds on the machine that is connecting, but my machine has EST time, so can anyone explain why I'm having this? and what can I do to set the current timestamp for my database to EST?

I've personally found it to be a lot more reliable to set the timezone in PHP, then grab the timestamp there and pass this to your MySQL query.
Something like:
date_default_timezone_set('America/New_York');
$curtimestamp = date('Y-m-d G:i:s', time());
Then use the value of $curtimestamp in your queries.

The documentation may have been unclear.
time_zone=SYSTEM means that the MySQL Server time zone is derived from the host that the MySQL Server is running on, not the client system.
So, if the time zone on the MySQL server host is different from the time zone of the client host, that explains the behavior that you observe.
Each client (database session) has its own time_zone setting. When the connection is established, the setting is derived from the "default" time zone for the MySQL server.
The setting of this variable determines how DATETIME and TIMESTAMP values are interpreted, when values are sent to the database from the client, AND when existing values are pulled from the database.
A client can issue a SET time_zone statement to change the time_zone for the database session, e.g.
SET time_zone=CST6CDT
(Note that to use named values for time zones, the time_zone% tables in the mysql database must be populated.)
To set the "default" time_zone that will be used for new database connections, you can set the "global" time_zone variable:
SET GLOBAL time_zone=
(This change requires SUPER privilege, and it impacts ALL new database connections to the entire instance. Normally, this value is set in the MySQL server configuration file.)
For TIMESTAMP columns, MySQL stores those as UTC. The values returned to the client depend on the setting of the client time_zone. As a simple demonstration:
mysql> CREATE TABLE mytest
-> ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
-> , ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-> );
Query OK, 0 rows affected (0.11 sec)
mysql> SHOW VARIABLES LIKE 'time_zone';
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| time_zone | +00:00 |
+---------------+--------+
1 row in set (0.00 sec)
mysql> INSERT INTO mytest (id) VALUES (NULL);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM mytest;
+----+---------------------+
| id | ts |
+----+---------------------+
| 1 | 2015-01-09 15:41:25 |
+----+---------------------+
1 row in set (0.00 sec)
mysql> SET time_zone = 'CST6CDT';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM mytest;
+----+---------------------+
| id | ts |
+----+---------------------+
| 1 | 2015-01-09 09:41:25 |
+----+---------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO mytest (id) VALUES (NULL);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM mytest;
+----+---------------------+
| id | ts |
+----+---------------------+
| 1 | 2015-01-09 09:41:25 |
| 2 | 2015-01-09 09:41:25 |
+----+---------------------+
2 rows in set (0.00 sec)
mysql> SET time_zone = 'EST5EDT';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM mytest;
+----+---------------------+
| id | ts |
+----+---------------------+
| 1 | 2015-01-09 10:41:25 |
| 2 | 2015-01-09 10:41:25 |
+----+---------------------+
2 rows in set (0.00 sec)

Related

Adding a date to mysql value being inserted if value exists in column

I have a MySQL table like that is structured like this:
| uri | title |
_________________ _____________
Latest-Update Latest Update
Latest Update
where the uri column is an INDEX. I have occassional injections I perform into a mysql table, and the ERROR Duplicate Entry appears if i have 1 or more URI's with the same name. So i use PHP for the inejction, and want to append a date("m-d-y") to the end of the variable $uri when being inserted. My INSERT statement INSERT INTO table(uri,title) values('$uri', '$title'). I want to see if in the table that is being inserted to, before the INSERT happens, if i can tell if the $uri value already exists in the uri table, and if so, that variable will become $uri = $uri."-"date("m-d-y"); How can i tell? I have done some research and lead me to believe i should be using INSERT...ON DUPLICATE KEY UPDATE?
Most probably this could be due to your uri being a primary key. For this, you should probably create a surrogate key and that would allow duplication. If that is indeed what you need.
Not sure if you are interested in Triggers but you can depend on BEFORE INSERT trigger. Trigger requires to check if new uri being inserted has a dup entry and if yes, append dateStringOfYourFormat and insert.
Example:
mysql> drop table mytable;
Query OK, 0 rows affected (0.03 sec)
mysql> create table mytable( uri varchar(128) );
Query OK, 0 rows affected (0.05 sec)
mysql> drop trigger uri_modifier;
ERROR 1360 (HY000): Trigger does not exist
mysql> delimiter //
mysql> create trigger uri_modifier before insert on mytable
-> for each row
-> begin
-> if ( select count(uri) from mytable where uri=NEW.uri ) > 0 then
-> set #modified_uri_string=concat(NEW.uri, '-', date_add(sysdate(), interval floor(rand()*1e6) microsecond));
-> set NEW.uri=#modified_uri_string;
-> end if;
-> end//
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> delimiter ;
mysql>
mysql> set #my_new_uri_string = 'my_uri_string_to_search';
Query OK, 0 rows affected (0.00 sec)
mysql> set #modified_uri_string = #my_new_uri_string;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from mytable;
Empty set (0.00 sec)
mysql> insert into mytable values(#my_new_uri_string);
Query OK, 1 row affected (0.03 sec)
mysql> select #my_new_uri_string, #modified_uri_string;
+-------------------------+-------------------------+
| #my_new_uri_string | #modified_uri_string |
+-------------------------+-------------------------+
| my_uri_string_to_search | my_uri_string_to_search |
+-------------------------+-------------------------+
1 row in set (0.00 sec)
mysql> select * from mytable;
+-------------------------+
| uri |
+-------------------------+
| my_uri_string_to_search |
+-------------------------+
1 row in set (0.00 sec)
mysql> insert into mytable values(#my_new_uri_string);
Query OK, 1 row affected (0.03 sec)
mysql> select #my_new_uri_string, #modified_uri_string;
+-------------------------+----------------------------------------------------+
| #my_new_uri_string | #modified_uri_string |
+-------------------------+----------------------------------------------------+
| my_uri_string_to_search | my_uri_string_to_search-2012-05-03 02:21:39.983405 |
+-------------------------+----------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from mytable;
+----------------------------------------------------+
| uri |
+----------------------------------------------------+
| my_uri_string_to_search |
| my_uri_string_to_search-2012-05-03 02:21:39.983405 |
+----------------------------------------------------+
2 rows in set (0.02 sec)
mysql> insert into mytable values(#my_new_uri_string);
Query OK, 1 row affected (0.01 sec)
mysql> select #my_new_uri_string, #modified_uri_string;
+-------------------------+----------------------------------------------------+
| #my_new_uri_string | #modified_uri_string |
+-------------------------+----------------------------------------------------+
| my_uri_string_to_search | my_uri_string_to_search-2012-05-03 02:21:39.412580 |
+-------------------------+----------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from mytable;
+----------------------------------------------------+
| uri |
+----------------------------------------------------+
| my_uri_string_to_search |
| my_uri_string_to_search-2012-05-03 02:21:39.983405 |
| my_uri_string_to_search-2012-05-03 02:21:39.412580 |
+----------------------------------------------------+
3 rows in set (0.00 sec)
mysql>
mysql>
Make sure that if uri inserted is different than what passed in, you have a handle to know what the modified value is.

MySQL view column name capitalization

I'm in the process of upgrading our in-house applications from MySQL 5.0.45 to 5.1.41. In the old environment we had mirrored some tables using symlinks from one DB to another. For a few reasons, current versions of MySQL block that completely.
What seemed like the best replacement was using a view instead, but I'm having a problem. A few old tables have column names that are capitalized. However some of our application code (PHP) does a SELECT with the capitalized name and also some SELECTs with lower case column names. Which normally works fine because MySQL returns tables with a column name capitalized as you referenced it in the SELECT. However, with a view that doesn't seem to be the case. See the following:
create table t(A int);
Query OK, 0 rows affected (0.18 sec)
> create view v as select A from t;
Query OK, 0 rows affected (0.00 sec)
> insert into t values(47);
Query OK, 1 row affected (0.01 sec)
> select a from t;
+------+
| a |
+------+
| 47 |
+------+
1 row in set (0.00 sec)
> select a from v;
+------+
| A |
+------+
| 47 |
+------+
1 row in set (0.00 sec)
Notice that the capitalization of the column name returned in the SELECT queries is different whether or not you select from the table or the view. The table returns the capitalization as specified in your query at runtime; the view returns the capitalization when the view was created. This seems to be consistent through both versions of MySQL, both the command-line client and through the PHP library client.
One trick I discovered is that if you add a GROUP BY to the SELECT in the view it will use the capitalization in your query at runtime. Unfortunately that breaks updating through the view, which I need.
Is there any way to make the column name capitalization match the query at runtime, which doesn't involve going back and changing all of our application code?
I have to say I'm not 100 % sure, but I strongly suspect you can't get a matching case in your views without modifying the application code. Have a look at how the view is defined (I'm using MySQL 5.1.56):
mysql> show create view v;
+------+-----------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View | Create View | character_set_client | collation_connection |
+------+-----------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| v | CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost` SQL SECURITY DEFINER VIEW `v` AS select `t`.`A` AS `A` from `t` | utf8 | utf8_general_ci |
+------+-----------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
1 row in set (0.00 sec)
As you can see, MySQL adds a column alias (AS), and AFAIK there's no way to make it behave differently. Defining a column name explicitly has the same result:
mysql> create view v2 (viewa) as select A from t;
Query OK, 0 rows affected (0.02 sec)
mysql> select Viewa from v2;
+-------+
| viewa |
+-------+
| 47 |
+-------+
1 row in set (0.00 sec)
mysql> show create view v2;
+------+----------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View | Create View | character_set_client | collation_connection |
+------+----------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| v2 | CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t`.`A` AS `viewa` from `t` | utf8 | utf8_general_ci |
+------+----------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
1 row in set (0.00 sec)
Adding a (somewhat funny-looking) column alias in all your SQL queries would obviously fix the issue:
mysql> select a as a from v;
+------+
| a |
+------+
| 47 |
+------+
1 row in set (0.00 sec)
instead of,
mysql> select a from v;
use this (with an alias),
mysql> select a as a from v;
+------+
| a |
+------+
| 47 |
+------+
1 row in set (0.00 sec)
you must be use Mysql column alias like this:
select a as a from v;

mySQL TIME function and Timezone

I want to use the NOW() function with a specific timezone, say GMT+8 for a user and GMT-2 for another user. How can I achieve this?
I am guessing that the time for NOW() is related somewhat to the timezone and time of the SQL server, but I want it to be such that FN(GMT+8) always give me the NOW() in GMT+8 irregardless of the timezone the SQL server is in.
Mini question: How do i display/know the current time of the SQL server?
The NOW() function provides the current time in the local timezone of the server. If you wish to convert to a different timezone, you can use CONVERT_TZ()
UPDATE:
You can use a per-connection timezone (that doesn't affect the system timezone) and get the effect you want:
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2011-06-03 22:40:51 |
+---------------------+
1 row in set (0.00 sec)
mysql> SET time_zone = '+08:00';
Query OK, 0 rows affected (0.00 sec)
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2011-06-04 10:41:15 |
+---------------------+
1 row in set (0.00 sec)

Change MySQL time zone without super permissions

I added this line to my config.inc.php file.
$query = "SET SESSION time_zone = 'Europe/Rome'";
if (mysql_query($query, DB_LINK) == FALSE) {
die(mysql_error(DB_LINK));
}
It doesn't give me any error, but when I use the NOW() or the CURRENT_TIMESTAMP() function it saves the record with a wrong time.
How can I set the date time zone in MySQL without the super permissions?
Assuming you are using 5.5, if you see http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html, it says:
mysql> SET time_zone = timezone;
It also says:
The current session time zone setting affects display and storage of time values that are zone-sensitive. This includes the values displayed by functions such as NOW() or CURTIME(), and values stored in and retrieved from TIMESTAMP columns. Values for TIMESTAMP columns are converted from the current time zone to UTC for storage, and from UTC to the current time zone for retrieval.
The current time zone setting does not affect values displayed by functions such as UTC_TIMESTAMP() or values in DATE, TIME, or DATETIME columns. Nor are values in those data types stored in UTC; the time zone applies for them only when converting from TIMESTAMP values. If you want locale-specific arithmetic for DATE, TIME, or DATETIME values, convert them to UTC, perform the arithmetic, and then convert back.
So try it without the SESSION and see if it works, and also check that select ##session.time_zone;
gives you the right timezone.
EDIT: you may just have an issue with your database. I just tried this on one of my databases (5.5.8) and it worked, but it failed on 5.0.51. So you may need a db upgrade.
mysql> select CURRENT_TIMESTAMP();
+---------------------+
| CURRENT_TIMESTAMP() |
+---------------------+
| 2011-05-29 14:33:06 |
+---------------------+
1 row in set (0.00 sec)
mysql> set time_zone = 'Europe/Rome';
Query OK, 0 rows affected (0.00 sec)
mysql> select CURRENT_TIMESTAMP();
+---------------------+
| CURRENT_TIMESTAMP() |
+---------------------+
| 2011-05-29 16:33:11 |
+---------------------+
1 row in set (0.00 sec)
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.5.8-log |
+-----------+
1 row in set (0.00 sec)
Erm I'm not sure how to set time zone with mysql...
but i prefer to set the time zone with php...
date_default_timezone_set('Europe/Rome');

php date() vs mysql MONTH()

i have this unix timestamp value: 1275364800 (1st june 2010).
When printing that value with php:
echo date('m',1275364800)
it returns 6 (thats ok)
But when i select a field from a database: select MONTH(FROM_UNIXTIME(1275364800)) AS month it returns 5
Why?
BTW, if i run this query select FROM_UNIXTIME(1275364800) AS q i get 2010-05-31 23:00:00
To set locales in MySql do the following.
First check what your local is:
mysql> SELECT ##lc_time_names;
+-----------------+
| ##lc_time_names |
+-----------------+
| en_US |
+-----------------+
To make sure its using the correct, If this is corrent the change your apache / php locale.
To change you locale in MySql
mysql> SET lc_time_names = 'en_UK';
Query OK, 0 rows affected (0.00 sec)
en_UK being what you wish to change it to!
mysql> SELECT ##lc_time_names;
+-----------------+
| ##lc_time_names |
+-----------------+
| en_UK |
+-----------------+
Hope this helps you!.
Because 1275364800 is 2010-05-31 not 1st june 2010 in mysql's locale. Are these being run on different machines?

Categories