Populating a table from query results (mysql) - mysql

I would like to fill a table with the results of a query on existing table. How can I do that?

(You don't need to match the table schemas)
INSERT tbl_name (col1, col2)
SELECT value1, value2
FROM othertable
See the reference for INSERT ... SELECT Syntax

insert into table_name ...
select * from table_name where ....
The target table and the source query must match in number of columns and datatypes
See this link

You can even create tables this way, though there the column names must match, or the select results are put in automatically added columns:
mysql> create table foo ( id int primary key auto_increment, bar datetime )
-> select now() as bar, now() as baz from dual;
Query OK, 1 row affected, 1 warning (0.06 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from foo;
+----+---------------------+---------------------+
| id | bar | baz |
+----+---------------------+---------------------+
| 1 | 2009-03-10 17:01:35 | 2009-03-10 17:01:35 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)

Related

SQL Insert many rows - one value changes - number of rows is dynamic

I need to do do an insert where 2 values will be constant and the third will change. So, something like the following:
INSERT INTO
`example_table`(column_a, column_b,column_c)
SELECT 1, [3,4], 409187710
from `example_table`
Desired Result:
column_a
column_b
column_c
1
3
409187710
1
4
409187710
Just to be clear the number of values I need to insert into column_b will vary - sometimes I will need to insert 2 values, sometimes I may need to insert 10 values, but columns a and c will always have the same values. How do I perform such an insert?
My question differs from this question in that a sql case statement will not suffice. This is a different kind of problem.
MySQL 8.0 has a new kind of statement: VALUES.
mysql> create table example_table (column_a int, column_b int, column_c int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into example_table
-> select 1, column_0, 409187710 from (values row(3), row(4)) as t;
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from example_table;
+----------+----------+-----------+
| column_a | column_b | column_c |
+----------+----------+-----------+
| 1 | 3 | 409187710 |
| 1 | 4 | 409187710 |
+----------+----------+-----------+
If you use a version of MySQL that doesn't support the VALUES statement, you can use this syntax:
mysql> insert into example_table
-> select 1, b, 409187710 from (select 3 as b union select 4) as t;

MySQL: Cannot update JSON column to convert value from float to integer

I have a MySQL table with a JSON column. I want to update some rows in the JSON column to change a json value from a float to an integer. e.g {"a": 20.0} should become {"a": 20}. It looks like MySQL finds these 2 values equivalent, so it never bothers to update the row.
Here is the state of my test table:
mysql> describe test;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| id | int | NO | PRI | NULL | |
| val | json | YES | | NULL | |
+-------+------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> select * from test;
+----+-------------+
| id | val |
+----+-------------+
| 1 | {"a": 20.0} |
+----+-------------+
1 row in set (0.00 sec)
My aim is to change val to {"a": 20}
I've tried the following queries:
mysql> update test set val=JSON_OBJECT("a", 20) where id=1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
(0 rows changed)
mysql> update test
set val=JSON_SET(
val,
"$.a",
FLOOR(
JSON_EXTRACT(val, "$.a")
)
)
where id=1;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
(0 rows changed)
mysql> insert into test (id, val) values (1, JSON_OBJECT("a", 20)) ON DUPLICATE KEY UPDATE id=VALUES(id), val=VALUES(val);
Query OK, 0 rows affected, 2 warnings (0.00 sec)
(0 rows affected)
It looks like it doesn't matter how I try to write it, whether I attempt to modify the existing value, or specify a whole new JSON_OBJECT. So I'm wondering if the reason is simply that MySQL considers the before & after values to be equivalent.
Is there any way around this?
(This does not address the original Question, but addresses a problem encountered in Answering it.)
Gross... 8.0 has a naughty history of all-too-quickly removing something after recently deprecating it. Beware. Here is the issue with VALUES from the Changelog for 8.0.20:
----- 2020-04-27 8.0.20 General Availability -- -- -----
The use of VALUES() to access new row values in INSERT ... ON DUPLICATE KEY UPDATE statements is now deprecated, and is subject to removal in a future MySQL release. Instead, you should use aliases for the new row and its columns as implemented in MySQL 8.0.19 and later.
For example, the statement shown here uses VALUES() to access new row values:
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
Henceforth, you should instead use a statement similar to the following, which uses an alias for the new row:
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new
ON DUPLICATE KEY UPDATE c = new.a+new.b;
Alternatively, you can employ aliases for both the new row and each of its columns, as shown here:
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new(m,n,p)
ON DUPLICATE KEY UPDATE c = m+n;
For more information and examples, see INSERT ... ON DUPLICATE KEY UPDATE Statement.

How to update data in table if data is match other then insert in mysql

Insert a row in sql if any match then update it.
I tried it
INSERT INTO test (name, email)
SELECT * FROM (SELECT 'Rupert', 'Somewhere#s.com') AS tmp
WHERE NOT EXISTS (
SELECT name FROM test WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `test`;
+----+--------+-----------------+
| id | name | email |
+----+--------+-----------------+
| 1 | Rupert | Somewhere#s.com |
+----+--------+-----------------+
This is only work for checking duplicate entry. but i want if no enrty found then insert it or other than update it.
INSERT INTO test (name, email)
SELECT * FROM (SELECT 'Rupert', 'Somewhere#somewhere.com') AS tmp
WHERE NOT EXISTS (
SELECT name FROM test WHERE name = 'Rupert'
) LIMIT 1;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
SELECT * FROM `test`;
+----+--------+-----------------+
| id | name | email |
+----+--------+-----------------+
| 1 | Rupert | Somewhere#s.com |
+----+--------+-----------------+
You can use ON DUPLICATE KEY
first, you have to create unique index:
ALTER TABLE testADD UNIQUE email(email`);
thus, if you insert a record with the same email value, it will update the record.
INSERT INTO test (name, email) VALUES("Rupert", "Somewhere#s.com")
ON DUPLICATE KEY UPDATE name="Rupert", email="Somewhere#s.com"
if it's a new email, it will create a new record
First of all you need to RUN this query
ALTER TABLE test ADD CONSTRAINT email UNIQUE (email);
After Then use this it will update your record if exist
INSERT INTO test (name,email) VALUES ('Gorilla','Somewhere#s.com') ON DUPLICATE KEY UPDATE email = "Somewhere#somewhere.com"

How to extract unique nested variable names out of one string variable?

Case
In our MySql database the data is stored in combined json-strings like this:
| ID | DATA |
| 100 | {var1str: "sometxt", var2double: 0,01, var3integer: 1, var4str: "another text"} |
| 101 | {var3integer: 5, var2double: 2,05, var1str: "txt", var4str: "more text"} |
Problem
Most of the DATA-fields hold over 2500 variables. The order of variables in the DATA-string is random (as shown in above example). Right now we only know how to extract data with the following querie:
select
ID,
json_extract(DATA,'var1str'),
json_extract(DATA,'var2double'),
FROM table
With this querie, only the values of var1str and var2double will be returned as result. Values of variable 3 and 4 are ignored. There is no overview of what possible variables are hiding in the data fields.
With almost 60.000 entries and over 3.000 possible unique variable names, I would like to create a query that loops through all of the 60.000 DATA-fields and extracts every unique variable name that is found in there.
Solution?
The querie I am looking for would give the following result:
var1str
var2double
var3integer
var4str
My knowledge of MySql is very limited. Any direction given to get to this solution is much appreciated.
What version of MySQL are you using?.
From MySQL 8.0.4 and later JSON_TABLE function is supported and can be useful in this case.
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 8.0.11 |
+-----------+
1 row in set (0.00 sec)
mysql> DROP TABLE IF EXISTS `table`;
Query OK, 0 rows affected (0.09 sec)
mysql> CREATE TABLE IF NOT EXISTS `table` (
-> `ID` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
-> `DATA` JSON NOT NULL
-> ) AUTO_INCREMENT=100;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `table`
-> (`DATA`)
-> VALUES
-> ('{"var1str": "sometxt", "var2double": 0.01, "var3integer": 1, "var4str": "another text"}'),
-> ('{"var3integer": 5, "var2double": 2.05, "var1str": "txt", "var4str": "more text"}');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT
-> DISTINCT `der`.`key`
-> FROM
-> `table`,
-> JSON_TABLE(
-> JSON_KEYS(`DATA`), '$[*]'
-> COLUMNS(
-> `key` VARCHAR(64) PATH "$"
-> )
-> ) `der`;
+-------------+
| key |
+-------------+
| var1str |
| var4str |
| var2double |
| var3integer |
+-------------+
4 rows in set (0.01 sec)
Be aware of the Bug #90610 ERROR 1142 (42000) when using JSON_TABLE.

Set column's default display to hexadecimal format

I'm looking for way to create a MySQL column where a SELECT statement will automatically display any value formatted as hexadecimal:
1 -> 0x1
16 -> 0x10
Here is an example that achieved basically this result, but the problem is that any user of this data will have to do the processing (http://sqlfiddle.com/#!9/3bc633/2):
Create data:
CREATE TABLE t1 (
c1 int
);
INSERT INTO t1 (c1) VALUES
(0x1),
(0x10);
Select the data:
SELECT c1, CONCAT('0x', HEX(c1))
FROM t1;
I would like to set a property on the column or table, to achieve this result with a simple SELECT c1.
CREATE TABLE t1 (
c1 int,
c2 varchar(32) GENERATED ALWAYS AS (CONCAT('0x', HEX(c1)))
);
MariaDB [test]> INSERT INTO t1 (c1) VALUES
-> (0x1),
-> (0x10);
Query OK, 2 rows affected (0.14 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [test]> select * from t1;
+------+------+
| c1 | c2 |
+------+------+
| 1 | 0x1 |
| 16 | 0x10 |
+------+------+
2 rows in set (0.00 sec)
Or, if you use an older version, it will probably be
CREATE TABLE t1 (
c1 int,
c2 varchar(32) AS (CONCAT('0x', HEX(c1))) VIRTUAL
);
But the same principle apply.