MYSQL CURRENT_TIMESTAMP only applied on update - mysql

I have a database with a column named date (timestamp) which is set to default CURRENT_TIMESTAMP. This used to work fine, however after migrating the database to a different server the timestamp only gets applied after an UPDATE query is performed, an INSERT query just sets it to "0000-00-00 00:00:00".

I suspect that whatever is doing the insert is putting an empty string into the field. Look at this result;
MariaDB [horizon]> create table foo (t timestamp default current_timestamp not null);
Query OK, 0 rows affected (0.02 sec)
MariaDB [horizon]> insert into foo values ('');
Query OK, 1 row affected, 1 warning (0.01 sec)
MariaDB [horizon]> select * from foo;
+---------------------+
| t |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)
I would check the code that is doing the insert - if it's coming from a web form the form itself could be submitting an empty string. You really need to insert null or leave the column out of the INSERT to get the default.
MariaDB [horizon]> insert into foo values (null);
Query OK, 1 row affected (0.01 sec)
MariaDB [horizon]> insert into foo values ();
Query OK, 1 row affected (0.00 sec)
MariaDB [horizon]> select * from foo;
+---------------------+
| t |
+---------------------+
| 0000-00-00 00:00:00 |
| 2017-09-19 21:41:16 |
| 2017-09-19 21:41:20 |
+---------------------+
3 rows in set (0.00 sec)

Related

Is there any way to assign default DbNull value to JSON column in MySQL?

I'm using MySQL version '8.0.28' and I'm trying to assign a default value to JSON column to one table in MySQL workbench.
Have tried this Mysql set default value to a json type column but it didn't worked out.
Any pointers or help is welcomed.
If you want a NULL to be the default, you don't need to declare that. It's the "default default" so to speak.
Here are a few different ways, tested on MySQL 8.0.29.
mysql> create table mytable (id serial primary key, j json);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into mytable () values ();
Query OK, 1 row affected (0.00 sec)
mysql> insert into mytable set j = null;
Query OK, 1 row affected (0.01 sec)
mysql> insert into mytable (id) values (default);
Query OK, 1 row affected (0.00 sec)
mysql> select * from mytable;
+----+------+
| id | j |
+----+------+
| 1 | NULL |
| 2 | NULL |
| 3 | NULL |
+----+------+
You can't set a

MySQL Insert ENUM field is left blank

So i'm trying to insert data with the query below. The columns releases_isMultipack, releases_isChase, releases_hasChase and releases_isAssortment are all enum('0', '1') type. 0 and 1 represent false and true.
INSERT INTO releases (releases_uid, releases_title, releases_releaseDate, releases_boxNumber, releases_hobbyDbId, releases_isMultipack, releases_itemNumber, releases_isChase, releases_hasChase, releases_referenceUrl, releases_componentNumber, releases_isAssortment, releases_craftProductId, releases_craftComponentId)
VALUES ('fa4d5128-407a-4c2b-8970-99a36a72b030', 'Woodsy Owl', '2021-03-26T16:05:00-07:00', '', NULL, 0, '52390', 0, 1, 'woodsy-owl-1', '52390a', 0, 9518039, 9518035)
The query works fine, however just leaves the ENUM columns blank even though a value is provided in the insert statement.
Does anyone know why this is happening?
There's a difference between 0 and '0'.
Here's a demo. I get a blank if I insert 0 because that's not the value in the enum.
mysql> create table releases (releases_isMultipack enum('0','1'));
Query OK, 0 rows affected (0.06 sec)
mysql> insert into releases values (0);
Query OK, 1 row affected, 1 warning (0.03 sec)
mysql> show warnings;
+---------+------+-----------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------+
| Warning | 1265 | Data truncated for column 'releases_isMultipack' at row 1 |
+---------+------+-----------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from releases;
+----------------------+
| releases_isMultipack |
+----------------------+
| |
+----------------------+
1 row in set (0.00 sec)
But it works if I use '0':
mysql> insert into releases values ('0');
Query OK, 1 row affected (0.03 sec)
mysql> select * from releases;
+----------------------+
| releases_isMultipack |
+----------------------+
| |
| 0 |
+----------------------+

MySQL DEFAULT vs. MariaDB DEFAULT

I have table_a with and auto_increment column named id and string column named name.
Running the statement:
INSERT INTO table_a(id, name)VALUES(DEFAULT, 'test');
Results to (MySQL):
+----+------+
| id | name |
+----+------|
| 1 | test |
+----+------+
Running the similar statement in MariaDB results to:
+----+------+
| id | name |
+----+------|
| 0 | test |
+----+------+
Other scenario:
I tried editing the AUTO_INCREMENT value of the table to 30. MySQL inserts 30 while MariaDB inserts 0.
What is the difference of DEFAULT value in INSERT statement of MySQL and MariaDB? Is this a bug in MariaDB or it is working as intended?
This behavior is controlled by SQL_MODE='NO_AUTO_VALUE_ON_ZERO', both in MySQL and MariaDB. If you observe the difference, it's most likely because you have different sql_mode on the instances.
MariaDB [test]> CREATE TABLE t (id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.20 sec)
MariaDB [test]> SET SQL_MODE='';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> INSERT INTO t (id) VALUES (DEFAULT);
Query OK, 1 row affected (0.05 sec)
MariaDB [test]> SELECT * FROM t;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
MariaDB [test]> DROP TABLE t;
Query OK, 0 rows affected (0.14 sec)
MariaDB [test]> CREATE TABLE t (id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.30 sec)
MariaDB [test]> SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> INSERT INTO t (id) VALUES (DEFAULT);
Query OK, 1 row affected (0.03 sec)
MariaDB [test]> SELECT * FROM t;
+----+
| id |
+----+
| 0 |
+----+
1 row in set (0.00 sec)

How to SELECT JSON data stored in as text

I have to extract data from a MariaDB database where the owners have stored JSON data in varchar fields in the form:
[-100, -18.3, -10.1, 2.2, 5.8, ...]
I would like to be able to select individual entries from each of these JSON encoded text fields.
I have been reading about the many features of JSON support in MariaDB and I have looked at many examples of how data can be stored as JSON in text fields, but they all would require changes to how the data is inserted and/or the schema.
I cannot change the DB in any way. I have ReadOnly access.
The owners of the DB are currently using MariaDB 10.0, but I may be able to get them to upgrade to 10.1
In short, given the following (very simple example), how can I select the 2nd element in the ‘data’ field?
I assume using the JSON features is the way to go (given all the data is JSON), but is there another way? Performance isn't all that important.
MariaDB [mtest]> show columns from cal from mtest;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| data | varchar(255) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
1 row in set (0.00 sec)
MariaDB [mtest]> select * from cal;
+---------+
| data |
+---------+
| [10.1,12.0,16.78,18.9] |
+---------+
1 row in set (0.00 sec)
If you can upgrade to 10.1 (from MariaDB 10.1.9) via CONNECT can use JsonGet_Real function.
Try:
MariaDB [_]> SELECT VERSION();
+-----------------+
| VERSION() |
+-----------------+
| 10.1.14-MariaDB |
+-----------------+
1 row in set (0.00 sec)
MariaDB [_]> INSTALL SONAME 'ha_connect';
Query OK, 0 rows affected (0.01 sec)
MariaDB [_]> CREATE FUNCTION `jsonget_real` RETURNS REAL SONAME 'ha_connect.so';
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DROP TABLE IF EXISTS `cal`;
Query OK, 0 rows affected, 1 warning (0.01 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS `cal` (
-> `data` VARCHAR(255)
-> );
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> INSERT INTO `cal`
-> (`data`)
-> VALUES
-> ('[10.1,12.0,16.78,18.9]');
Query OK, 1 row affected (0.00 sec)
MariaDB [_]> SELECT `data` FROM `cal`;
+------------------------+
| data |
+------------------------+
| [10.1,12.0,16.78,18.9] |
+------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `jsonget_real`(`data`, '[1]', 2) FROM `cal`;
+--------------------------------+
| jsonget_real(`data`, '[1]', 2) |
+--------------------------------+
| 12.00 |
+--------------------------------+
1 row in set (0.00 sec)

Custom time in MYSQL on update

I have a table with some rows and within them there is a definition that goes like this:
`metric_update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
So what i actually want it to do is to automatically insert a timestamp when inserting data into that table. And it does. But what I need is to write a GMT based time into that field (current server time is like GMT+2).
Is there a way to say to MYSQL to do such thing?
If your server time and timezone settings are configured correctly, then internally all times stored in TIMESTAMP columns are converted to GMT (since that's what Unix timestamp mandates). They're converted back to your session timezone when you retrieve this data. If you want it presented in GMT timezone, you need to do conversion while retrieving data not while inserting.
See the console dump below for example. You can run these commands yourself to check.
mysql> use test;
Database changed
mysql> -- let's create a table we'll be working with
mysql> CREATE TABLE tsTable (
-> ID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
-> );
Query OK, 0 rows affected (0.08 sec)
mysql> -- let's check current time as well as timezone settings
mysql> SELECT CURTIME(),##global.time_zone, ##session.time_zone;
+-----------+--------------------+---------------------+
| CURTIME() | ##global.time_zone | ##session.time_zone |
+-----------+--------------------+---------------------+
| 16:25:51 | SYSTEM | +02:00 |
+-----------+--------------------+---------------------+
1 row in set (0.05 sec)
mysql> -- inserting empty row to table to trigger auto timestamp
mysql> INSERT INTO tsTable VALUES (null,null);
Query OK, 1 row affected (0.00 sec)
mysql> -- looks like the time in my local timezone is stored in table
mysql> SELECT * FROM tsTable;
+----+---------------------+
| ID | ts |
+----+---------------------+
| 1 | 2011-07-28 16:26:25 |
+----+---------------------+
1 row in set (0.00 sec)
mysql> -- switching to GMT
mysql> SET SESSION time_zone = '+0:00';
Query OK, 0 rows affected (0.00 sec)
mysql> -- check current time and timezone settings again
mysql> SELECT CURTIME(),##global.time_zone, ##session.time_zone;
+-----------+--------------------+---------------------+
| CURTIME() | ##global.time_zone | ##session.time_zone |
+-----------+--------------------+---------------------+
| 14:27:53 | SYSTEM | +00:00 |
+-----------+--------------------+---------------------+
1 row in set (0.00 sec)
mysql> -- note: CURTIME() returns time two hours 'earlier' than before
mysql> -- let's see what's stored in the table again
mysql> SELECT * FROM tsTable;
+----+---------------------+
| ID | ts |
+----+---------------------+
| 1 | 2011-07-28 14:26:25 |
+----+---------------------+
1 row in set (0.00 sec)
mysql> -- TIMESTAMP is two hours 'earlier' than before too! Magick!
INSERT INTO table_name(column1, metric_update_time) VALUES('dummy', CONVERT_TZ(CURRENT_TIMESTAMP,'+02:00','+03:00');
This will convert the inserted timestamp from GMT+2 to GMT+3.