MySQL nested INSERT statements - mysql

Can you nest INSERT statements in MySQL?
I have this schema:
T1(ids)
T2(id, x, ...)
T3(id, y, ...)
What I need to do is copy data from table T2 to table T3 while modifying some fields and adding new data to T3, then updating the parent table T1 to reference the new records.
I know we can run a command like this to copy records between tables:
INSERT INTO T3 SELECT id+1000, X, 'new', ... FROM T2
However I then need to pipe the new records that have been created into T1.
Something like this:
INSERT INTO T1 SELECT id FROM
(INSERT INTO T3 SELECT id+1000, X, 'new', ... FROM T2)
Is this possible? My ids are not auto-increment, T1 is a list of id's of T2 and T3 with some additional data per records. T2 and T3 are not identical tables.
I just need to copy data from T3 to T2 with new id's and then update T1 to reflect the new records that were created, all in 1 transaction if possible.

Related

Update all columns on duplicate in Insert on select

I have two tables (say t1 and t2). I want to insert all records from t2 to t1. I can do this by using the query -
Insert into t1 select * from t2
While inserting, there might be duplicates. How to update all columns in table t1 from the t2 table in case of duplicates. We can do it this way -
Insert into t1 select * from t2 on duplicate update t1.a=t2.a...
But there are more than 60 columns in table t2. Is there any way to update all columns at once?

Compare 2 mysql tables

I have 2 tables (t1 with 581978 rows,t2 with 581196 rows) containing some common fields (f1,f2,f3). The tables normally have the same number of rows, but can get out of sync. When this happens I'd like to identify the rows in t1 that are not in t2. The following python code (just use the 'select stmt' for mysql without python) identified the additional 782 rows in t1 but on my ageing iMac took over 12hrs! Is there a more efficient method?
orphans = ("select t1.f1,t1.f2,t1.f3 from t1 where not exists " \
"(select 1 from t2 where t2.f1=t1.f1 and t2.f2=t1.f2 and " \
"t2.f3=t1.f3)")
cursor.execute(orphans)
for i,(f1,f2,f3) in enumerate(cursor):
print(i+1,"orphans {:<10} {:<10} {<:8}".format(f1,f2,f3))
db-fiddle code (Is there a free db-fiddle, seems I can't save without upgrading to pro?)
CREATE DATABASE if not exists SO_61403216;
use SO_61403216;
drop table if exists t1,t2;
create table t1 (f1 varchar(1),f2 int(2),f3 int(2),f4 int(2));
create table t2 (f1 varchar(1),f2 int(2),f3 int(2),f4 int(2),f5 int(2));
insert into t1 (f1,f2,f3,f4) values ("A",2,3,4);
insert into t1 (f1,f2,f3,f4) values ("B",2,3,4);
insert into t1 (f1,f2,f3,f4) values ("C",2,3,4);
insert into t1 (f1,f2,f3,f4) values ("D",2,3,4);
insert into t2 (f1,f2,f3,f4,f5) values ("A",2,3,44,55);
insert into t2 (f1,f2,f3,f4,f5) values ("B",2,3,99,99);
insert into t2 (f1,f2,f3,f4,f5) values ("C",2,3,99,99);
Query, which exposes the extra row in table t1 using both the "not exist" (preferred output) and "null" methods, which both take 0ms for these small tables, but same query takes hours with 500K+ rows - is there a better/quicker method?
use SO_61403216;
desc t1;
desc t2;
select * from t1;
select * from t2;
select t1.f1,t1.f2,t1.f3 from t1 where not exists (select 1 from t2 where t2.f1=t1.f1 and t2.f2=t1.f2 and t2.f3=t1.f3)
select * from t1 left join t2 on t1.f1=t2.f1 and t1.f2=t2.f2 and t1.f3=t2.f3 where t2.f1 is null;

How can I insert new rows in table 2 to table 1 comparing the ID?

I would like to know how I can insert new rows in my table 1 of table 2. The idea is that by comparing the two tables if in the second one you do not find the same ID in table 1 this inserts the new data in table 1.
This is the two table and the idea I want to do:
Tabla 1
ID-Name-Surname
1-Oriol-Molina
Tabla 2
ID-Name-Surname
1-Oriol-Molina
2-Ricard-Martin
And the result would be this:
Tabla 1
ID-Name-Surname
1-Oriol-Molina
2-Ricard-Martin
Tabla 2
ID-Name-Surname
1-Oriol-Molina
2-Ricard-Martin
Use the database to enforce data integrity. That is, if you don't want duplicate ids in the table, then declare a unique index/constraint:
create unique index unq_table1_id on table1(id);
Then, in MySQL, you can use on duplicate key update:
insert into table1 (id, name, surname)
select id, name, surname
from table2
on duplicate key update id = values(id);
The final statement is a no-op -- it does nothing except prevent an error.
The advantage of this approach is that the database will ensure that id is unique for any statement that inserts data into the table, not just this one.
You can use INSERT INTO .. SELECT with LEFT JOIN and IS NULL check, to fetch only those rows from Table2 which do no exist in Table1
INSERT INTO Table1 (ID, Name, Surname)
SELECT t2.ID, t2.Name, t2.Surname
FROM Table2 t2
LEFT JOIN Table1 t1 ON t1.ID = t2.ID
WHERE t1.ID IS NULL
You can try using a left join
insert into table1
select id, name, surname from table2 left join table1 on table2.id=table1.id
where table1.id is null

SQL: Update table when the table copying from has duplicate entries

I have a table which contains unique names, call it table1. I have another table which contains the same names but each name occurs several times, call it table2. Now, I want to copy data from table2 to table1 corresponding to the names. And if table2 has multiple records by the same name, I want the corresponding new records to be created in table1.
TABLE1 TABLE2
NAME NAME
A A
B A
C B
D B
Following the little chat int he comments, you could try this:
UPDATE t1
set columnx = t2.columnx
FROM table1 t1
LEFT JOIN table2 t2 on t2.name = t1.name
WHERE t2.name is null
To achieve your full requirements, you may find it more useful to have multiple queries accomplish the one task.

Compare two identical tables MySQL

I'm currently in the process of converting data, in a table, which is why I've created a new table, identical to the old one, but empty.
I've run my data converter, and I have a difference in row count.
How do I select all rows that are different from the two tables, leaving out the primary key identifier (that differs on every entry).
select * from (
SELECT 'Table1',t1.* FROM table1 t1 WHERE
(t1.id)
NOT IN (SELECT t2.id FROM table2 t2)
UNION ALL
SELECT 'Table2',t2.* FROM table2 t2 WHERE
(t2.id)
NOT IN (SELECT t1.id FROM table1 t1))temp order by id;
You can add more columns in where columns to check on more info.
Try and see if this helps.