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)
Related
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
I have a table eav_attribute which have a below structure,
I have mistakenly deleted one record from this table with auto increment attribute id column with value 961.
Now I want that column again with same attribute id value.
But when I am inserting that column it is adding with auto increment value i.e. around 1500.
I want to add new coulmn with attribute id 961
I tried to change set AUTO_INCREMENT to 961 before adding column.
ALTER TABLE eav_attribute AUTO_INCREMENT = 961;
But its not working. Please provide any suggestion.
You can override the auto increment column. For example
MariaDB [sandbox]> drop table if exists t;
Query OK, 0 rows affected (0.14 sec)
MariaDB [sandbox]> create table t (id int auto_increment primary key,val varchar(1));
Query OK, 0 rows affected (0.27 sec)
MariaDB [sandbox]> insert into t (val) values
-> ('a'),('b'),('C');
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 2 | b |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> delete from t where val = 'b';
Query OK, 1 row affected (0.03 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 3 | C |
+----+------+
2 rows in set (0.00 sec)
MariaDB [sandbox]> insert into t values (2,'b');
Query OK, 1 row affected (0.02 sec)
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 2 | b |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]> show create table t;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`val` varchar(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
I would strongly advice you test this thoroughly...
I have two Tables (account2017) and (account2018) and I want to add a 2 at the end of the names in the name row for one of the tables, but only if both tables contain the same name. Adding the 2 for that name, which has lower points value.
Overall a solution to merge two tables with unique key (name), but to decide which row gets a 2 added at his end of name, should be followed by lower points.
For example if table account2017 and account2018 have both "Alex" in the name column, add a 2 at the end of the name (=Alex2) to that table, which has lower value in points column. As Alex in accounts2017 has 20 points, and Alex in accounts2018 has only 15 points, Alex name will be changed to Alex2 for accounts2018. Accounts2017 will be untouched.
Any idea how it can work?
If I'm understanding correctly, sounds like you need to use 2 separate update statements, using exists to match the criteria:
update account2017
set name = concat(name, '2')
where exists (
select 1
from account2018
where account2017.name = account2018.name and account2017.score < account2018.score)
update account2018
set name = concat(name, '2')
where exists (
select 1
from account2017
where account2018.name = account2017.name and account2018.score < account2017.score)
You will need to do this in 2 queries. Syntax will depend on what you are using (MySQL, SQL Server, SQLite) but here is the MySQL Version:
UPDATE accounts2017 table1 SET name = concat(name, '2') WHERE exists (SELECT 1 FROM accounts2018 table2 WHERE table1.name = table2.name AND table1.score < table2.score);
Then you can just flip the query around to update the 2018 table.
You can do this using a multi-table update. This relies on mysql recognising no change has been made to account2017 (proved by the fact that timestamp has not changed) but beware both before and after triggers fire.
MariaDB [sandbox]> drop table if exists account2017,account2018;
Query OK, 0 rows affected (0.39 sec)
MariaDB [sandbox]> create table account2017(name varchar(10), points int,ts timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.20 sec)
MariaDB [sandbox]> create table account2018(name varchar(10), points int,ts timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.29 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> drop trigger if exists t;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [sandbox]> delimiter $$
MariaDB [sandbox]> create trigger t before update on account2017
-> for each row
-> begin
-> insert into debug_table(msg) values (concat('before:',old.name,':',new.name));
-> end $$
Query OK, 0 rows affected (0.07 sec)
MariaDB [sandbox]> delimiter ;
MariaDB [sandbox]>
MariaDB [sandbox]> drop trigger if exists t1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [sandbox]> delimiter $$
MariaDB [sandbox]> create trigger t1 after update on account2017
-> for each row
-> begin
-> insert into debug_table(msg) values (concat('after:',old.name,':',new.name));
-> end $$
Query OK, 0 rows affected (0.08 sec)
MariaDB [sandbox]> delimiter ;
MariaDB [sandbox]>
MariaDB [sandbox]> insert into account2017 (name,points) values('alex',20);
Query OK, 1 row affected (0.02 sec)
MariaDB [sandbox]> insert into account2018 (name,points) values('alex',15);
Query OK, 1 row affected (0.01 sec)
MariaDB [sandbox]> truncate table debug_table;
Query OK, 0 rows affected (0.17 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from account2017;
+------+--------+---------------------+
| name | points | ts |
+------+--------+---------------------+
| alex | 20 | 2018-12-11 16:49:25 |
+------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]> select * from account2018;
+------+--------+---------------------+
| name | points | ts |
+------+--------+---------------------+
| alex | 15 | 2018-12-11 16:49:25 |
+------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select sleep(60);
+-----------+
| sleep(60) |
+-----------+
| 0 |
+-----------+
1 row in set (1 min 0.00 sec)
MariaDB [sandbox]> update account2017 join account2018 on account2017.name = account2018.name
-> set account2017.name = case when account2017.points < account2018.points then concat(account2017.name,'2') else account2017.name end,
-> account2018.name = case when account2018.points < account2017.points then concat(account2018.name,'2') else account2018.name end
-> where 1 = 1;
Query OK, 1 row affected (0.04 sec)
Rows matched: 2 Changed: 1 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> select * from account2017;
+------+--------+---------------------+
| name | points | ts |
+------+--------+---------------------+
| alex | 20 | 2018-12-11 16:49:25 |
+------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]> select * from account2018;
+-------+--------+---------------------+
| name | points | ts |
+-------+--------+---------------------+
| alex2 | 15 | 2018-12-11 16:50:26 |
+-------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]> select * from debug_table;
+----+------------------+------+
| id | msg | MSG2 |
+----+------------------+------+
| 1 | before:alex:alex | NULL |
| 2 | after:alex:alex | NULL |
+----+------------------+------+
2 rows in set (0.00 sec)
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)
I opened two command windows to work with my Database (MySQL5).
Below is table structure I'm working with (It should be noted that I've turned off the auto commit by executing set autocommit=0;):
Table Structure:
CREATE TABLE `ajax`.`zipcodes` (
`ZIPCODE` varchar(5) NOT NULL,
`CITY` varchar(50) DEFAULT NULL,
`STATE` varchar(2) DEFAULT NULL,
PRIMARY KEY (`ZIPCODE`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Below is sequence of activities:
Step 1:
In command window 1, I executed below commands and you could also see the output:
mysql> insert into ajax.zipcodes values(5, 'Wil', 'AK');
Query OK, 1 row affected (0.00 sec)
Step 2
In second command window, I fired below command and it hangs (it seems waiting for commit command to be issues from previous window)
mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
Step 3
I went to Command window#1, and executed commit; you could see the output below:
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
At the same time, i could see that second window that was earlier hanging, also executed the command and printed below output:
mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
Query OK, 1 row affected (3.63 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Step 4
Now I issues commit in my second window to ensure that all the changes gets commited properly even the second session:
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
Step 5
Now since commit has been issued from both windows I thought that everything is all right and the two session also must be in sync, so I went to 1st command window and issues below command:
mysql> select * from zipcodes where zipcode=5;
+---------+------+-------+
| ZIPCODE | CITY | STATE |
+---------+------+-------+
| 5 | Wil | AK |
+---------+------+-------+
1 row in set (0.00 sec)
I was surprised because I was expecting City value to be 'Dublin' because changes from second command window (i.e. update) has been commited in Step 4, but i'm still getting Wil in City column.
What am I doing wrong here?
This is to do with isolation levels. If you raise your isolation level to SERIALIZABLE (the default in MySQL is REPEATABLE READS) you won't get "phantom reads".
Isolation levels and phantom reads are described on the Wikipedia page for database transaction isolation.
If I run this through as you did, but with the higher isolation level, I get the result you were expecting.
Session 1
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE `ajax`.`zipcodes` (
-> `ZIPCODE` varchar(5) NOT NULL,
-> `CITY` varchar(50) DEFAULT NULL,
-> `STATE` varchar(2) DEFAULT NULL,
-> PRIMARY KEY (`ZIPCODE`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.07 sec)
mysql> insert into ajax.zipcodes values(5, 'Wil', 'AK');
Query OK, 1 row affected (0.00 sec)
Session 2
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Query OK, 0 rows affected (0.00 sec)
mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
Session 1
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
Session 2
/* continued from previous (was frozen) */
Query OK, 1 row affected (7.54 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY | STATE |
+---------+--------+-------+
| 5 | Dublin | AK |
+---------+--------+-------+
1 row in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY | STATE |
+---------+--------+-------+
| 5 | Dublin | AK |
+---------+--------+-------+
1 row in set (0.00 sec)
Session 1
mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY | STATE |
+---------+--------+-------+
| 5 | Dublin | AK |
+---------+--------+-------+
1 row in set (0.00 sec)
NB: This doesn't necessarily mean that you should always be using SERIALIZABLE - there are trade-offs. Most notable is that the database will acquire a range lock when executing a SELECT and you'll get more locking-based conflicts.
Update - Explicitly Handling Transactions
Since we have autocommit=0; set in these scripts, we really should handle the transactions explicitly, rather than expecting a START TRANSACTION - although in most cases, the database behaves as you'd expect if you'd executed START TRANSACTION.
However, run the original example while explicitly starting and ending all transactions (including those that are just SELECT, and you get a different result:
Session 1
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE `ajax`.`zipcodes` (
-> `ZIPCODE` varchar(5) NOT NULL,
-> `CITY` varchar(50) DEFAULT NULL,
-> `STATE` varchar(2) DEFAULT NULL,
-> PRIMARY KEY (`ZIPCODE`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Query OK, 0 rows affected (0.07 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into ajax.zipcodes values(5, 'Wil', 'AK');
Query OK, 1 row affected (0.00 sec)
Session 2
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> update ajax.zipcodes set city='Dublin' where zipcode=5;
Session 1
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
Session 2
/* continued from previous (was frozen) */
Query OK, 1 row affected (8.32 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY | STATE |
+---------+--------+-------+
| 5 | Dublin | AK |
+---------+--------+-------+
1 row in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY | STATE |
+---------+--------+-------+
| 5 | Dublin | AK |
+---------+--------+-------+
1 row in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.04 sec)
Session 1
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from zipcodes;
+---------+--------+-------+
| ZIPCODE | CITY | STATE |
+---------+--------+-------+
| 5 | Dublin | AK |
+---------+--------+-------+
1 row in set (0.00 sec)