I have the following data:
table1:
id common_criteria member_id
1 some 1000
2 some1 500
3 some 100
4 some 200
3 some1 2000
table2
id member_id
The id columns are AUTOINCREMENT PRIMARY KEY on both tables
I need to insert into table2 three new rows (in this case) where common_criteria from table1 = 'some'
Expected result for table2:
id member_id
1 1000
2 100
3 200
I have tried:
INSERT into table2 (`member_id`)
VALUES (
SELECT `member_id` FROM table1 WHERE common_criteria = 'some'
)
But I get a syntax error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'SELECT member_id FROM table1 WHERE common_criteria = 'some')'
at line 1
You shouldn't need the VALUES part when you want to get the results from a SELECT. Instead you can simplify it to this:
INSERT into table2 (`member_id`)
SELECT `member_id`
FROM table1
WHERE common_criteria = 'some'
and it will insert all the rows returned by the SELECT.
Additional note (since people often ask this): If you had a scenario where some of the values are static every time, then you can do that too quite easily:
INSERT into table2 (`member_id`, `some_other_field`)
SELECT `member_id`, 'Static Text'
FROM table1
WHERE common_criteria = 'some'
In this case "Static Text" will be inserted every time into every row, no matter how many rows are returned (and inserted) as a result of the SELECT.
You can just do it like this:
INSERT INTO table2 (`member_id`)
SELECT `member_id` FROM table1 WHERE common_criteria = 'some'
Related
TL;DR (i.e. asking the question first):
Is there any way to write an INSERT INTO...SELECT FROM...GROUP BY...ON DUPLICATE KEY UPDATE statement using row alias(es) in the ON DUPLICATE KEY UPDATE clause instead of the col1 = VALUES(col1) syntax that has been deprecated and will be removed from future MySQL releases?
My searches of SO relating to this issue tend to all suggest using the deprecated VALUES() function, which is why I believe that my question is not a duplicate.
BACKGROUND (i.e. more info on how to reproduce the issue)
I have a table that comprises grouped records from another table. For simplicity in describing this issue, I've created two sample tables purely to illustrate:
items:
item_groups (below) was populated using the following SQL:
insert into item_groups (item_type,quantity) (select item_type, count(*) from items group by item_type order by item_type)
It also has a unique index on item_type:
Now, let's say that I add two more items to the items table, one with an item_type of 4 and one with a new item_type of 5. The quantity of item_type 4 in item_groups should be updated to 3 and a new row inserted for the item_type of 5 with quantity of 1.
Using the same INSERT statement I used above to initially populate the item_groups table, I now get an error, which is expected because of a duplicate key (4 of the 5 item_types currently in the items table are duplicates of the item_types that currently exist in the item_groups table):
Zero updates or inserts were completed due to this error. To remedy this, we would have historically used the ON DUPLICATE KEY UPDATE (occasionally abbreviated to ODKU below) clause like so including the VALUES() function:
insert into item_groups (item_type,quantity) (select item_type, count(*) from items group by item_type order by item_type) ON DUPLICATE KEY UPDATE quantity = VALUES(quantity);
The above INSERT...ON DUPLICATE KEY UPDATE statement with VALUES() DOES work (currently)...
However, I am also greeted with the following warning:
'VALUES function' is deprecated and will be removed in a future
release. Please use an alias (INSERT INTO ... VALUES (...) AS alias)
and replace VALUES(col) in the ON DUPLICATE KEY UPDATE clause with
alias.col instead
Now, I know how to write a simple INSERT...ODKU statement to be future-proof against the warning above (generically):
INSERT INTO `my_table` (col1,col2,col3) VALUES (1,2,3) AS new ON DUPLICATE KEY UPDATE col1 = new.col1, col2 = new.col2, col3 = new.col3
But let's insert more items into my items table and then use the above syntax for my more complicated INSERT...SELECT...ODKU statement into item_groups:
insert into item_groups (item_type,quantity) (select item_type, count(*) from items group by item_type order by item_type) AS new ON DUPLICATE KEY UPDATE quantity = new.quantity;
I get this error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'AS new ON DUPLICATE KEY UPDATE quantity =
new.quantity' at line 1
Adding "VALUES" prior to my SELECT subquery, like so...
insert into item_groups (item_type,quantity) VALUES (select item_type, count(*) from items group by item_type order by item_type) AS new ON DUPLICATE KEY UPDATE quantity = new.quantity;
I now get a new syntax error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'select item_type, count(*) from items group by
item_type order by item_type) AS ' at line 1
Finally, at my wit's end, I try adding another set of parentheses around the SELECT sub-query...
insert into item_groups (item_type,quantity) VALUES ((select item_type, count(*) from items group by item_type order by item_type)) AS new ON DUPLICATE KEY UPDATE quantity = new.quantity;
...and I still get an error:
ERROR 1136 (21S01): Column count doesn't match value count at row 1
This appears to be "progress" as I'm no longer getting syntax errors; however, I don't understand why the column count doesn't match the value count. My SELECT subquery pulls in 2 values for each row and the INSERT attempts to insert those into 2 columns for each row. So it would seem to me that 2 values -> 2 columns should not be an issue; yet it is.
CONCLUSION
I'm frankly not even sure what else to try, and I'm about ready to give up doing it this way and just write a simple SELECT, store those retrieved values in variables, and then use a simple INSERT to insert those values (wrapping everything in a transaction). However, if there is a way to do what I'm trying to do in one statement, I would appreciate anyone who can help me to do this.
From MySQL docs
Beginning with MySQL 8.0.20, an INSERT ... SELECT ... ON DUPLICATE KEY
UPDATE statement that uses VALUES() in the UPDATE clause, like this
one, throws a warning:
INSERT INTO t1 SELECT c, c+d FROM t2 ON DUPLICATE KEY UPDATE b =
VALUES(b); You can eliminate such warnings by using a subquery
instead, like this:
INSERT INTO t1 SELECT * FROM (SELECT c, c+d AS e FROM t2) AS dt ON
DUPLICATE KEY UPDATE b = e;
In simple words you could use a subquery as follows:
insert into item_groups (item_type,
quantity)
select * from ( select item_type , count(*) as new_quantity from items group by item_type ) as tbl
ON DUPLICATE KEY UPDATE quantity = new_quantity;
https://dbfiddle.uk/HoMLKMfd
You need a version mysql that is newer
8.0.30 and 8.0,31 this works
The use of VALUES() to refer to the new row and columns is deprecated beginning with MySQL 8.0.20, and is subject to removal in a future version of MySQL. Instead, use row and column aliases, as described in the next few paragraphs of this section.
so it shpuld work with 8.0.20 too
Besides security risks, with very update come new functions and old bugs are fixed.
Deploying for two Versions is bad, as you need more and more code to support more database version or to simulate functions you need, that you open your code to more and more bugs and insecurities.
So make a cut and use the latest Version
CREATE TABLE `my_table` (col1 int unique,col2 int ,col3 int)
INSERT INTO `my_table` (col1,col2,col3) VALUES (1,2,3) AS new
ON DUPLICATE KEY UPDATE col1 = new.col1, col2 = new.col2, col3 = new.col3
SELECT * FROM `my_table`
col1
col2
col3
1
2
3
fiddle
i am using MySql Workbench version 6.3.9 with mySql 5.6.35.
i have the following tables:
EQUIPMENT
eID | caochID | eName
COACH
coachID | coachName
SQLfiddle prepared http://sqlfiddle.com/#!9/e333d/1
eID is a primary key. there are multiple coachID's in different equipment, so there will be duplicate coachIDs with different equipment, but the eID will be unique as it is a primary key.
REQUIRED
i need to insert a row in the equipment table, if it does not already exist. If it exists, do nothing.
various posts online have pointed me towards two options:
a) INSERT...ON DUPLICATE KEY UPDATE...
b)INSERT...WHERE NOT EXISTS
PROBLEM i have problems with both of these solutions. for the first solution (ON DUPLICATE KEY UPDATE) the query inserts the row as required but does not update the existing row. instead it creates a new entry. for the second solution (WHERE NOT EXISTS) i get an error : SYNTAX ERROR: 'WHERE' (WHERE) is not a valid input at this position.
the sql query doesnt need to make any joins. i listed both tables so that you can see how they are related. the insert query i need will only insert for the equipment table.
You can insert by using a tmp table and ensuring that the same record is not existing from current table. Add limit 1 to ensure only one record is inserted. Below query will not insert since 1 and small ball exists.
INSERT INTO `Equipment` (`c_id`, `eName`)
SELECT * FROM (SELECT '1', 'small ball') tmp
WHERE NOT EXISTS (
SELECT c_id FROM Equipment WHERE `c_id`='1' and `eName` = 'small ball'
) LIMIT 1;
NOT EXISTS
insert into table2 (....) --- all if not columns ... destination
select ....
from table1 t1 --- source of data to check
where not exists (
select 1
from table2 t2
where t2.col = t1.col --- match source and destination table making sure table1 data is not in table2
)
How can I check in table_1 if value_a of column_a (and where value_b of column_b = 'x') already exists in column_a of table_2? If it's not present insert it and create a new row for the missing value_a in table_2?
Update: (What seems to work is this:)
INSERT INTO products
(key, category)
SELECT key, category
FROM accounts
WHERE category = 'vegan'
AND NOT EXISTS (SELECT *
FROM products
WHERE accounts.key = products.key);
Why don't you transform the column into a primary key ? You'll just have to handle the duplicate entry error code
EDIT :
The solution here is to use SELECT instead of WHERE (thanks to degr)
INSERT INTO tableA(`id`,`column1`)
SELECT 44,'Value of Column1' -- The values you want to insert
WHERE NOT EXISTS(SELECT * FROM table2 WHERE id=40) -- check that there is no matching with the request
AND 1=1 --additional conditions
AND NOT EXISTS(SELECT * FROM Table3 WHERE id=44); --additional conditions
I have to run two insert statements in two different tables.
The sqls are as under :
INSERT INTO Table1 ('t1_name', 't1_class') VALUES ('Joe','8');
Table1 has an autoincremental ti_id column
INSERT INTO Table2 ('t2_ti_id','t2_course') VALUES(< 'ti_id' from Table1 call >,
'English'),(< 'ti_id' from Table1 call >, 'Math').
So end result should have been, such that the autoincremental id set for table1 query is used in the table2 query
Table1
t1_id ti_name t1_class
1 Joe 8
Table2
t2_id t2_t1_id t1_course
1 1 English
2 1 Math
t1_id and t2_t1_id have a foreign key setup
Please tell me how to make thecalls from the same sql, so that i dont have to make a seperate perl script for this
Thanks in advance
Use last_insert_id()
Try this:
INSERT INTO Table1 (t1_name, t1_class) VALUES ('Joe','8');
SET #t1id = SELECT LAST_INSERT_ID();
INSERT INTO Table2 (t2_ti_id, t2_course)
VALUES (#t1id,'English')
I am new to mysql. I have a problem in inserting record to table1 if it does not exist in table2.I have 2 tables table1 and table2 in the form:
table1
dep_id start stop modified deleted
1 23456789 167921525 Yes No
2 34567812 345678145 Yes No
3 32789054 327890546 No No
table2
start stop modified deleted
23456789 167921525 No No
34567823 345678145 No No
32789053 727890546 No No
I am trying to insert values into table1's start and stop field values only if it does not exist in table2's "start" and "stop" columns. If it exists the I need to throw an error.
These tables do not have a primary key foreign key relationship.
I apologize for not knowing correct syntax but I have to do something like this in mysql and PHP.
Replace Into into table1 set 'start'=> $start,'stop' => $stop
(select 'start','stop' from table2 where table1.start and table1.stop not in table2.start and table2.stop);
How do I query these 2 tables to check if Table1.start and Table1.stop fields do not match with Table2.start and Table2.stop before inserting to table1?
You can do:
INSERT INTO table1 (start, stop)
SELECT a.*
FROM (SELECT 123456789 start, 234567890 stop) a
LEFT JOIN table2 b ON (a.start,a.stop) IN ((b.start,b.stop))
WHERE b.start IS NULL
Where 123456789 and 234567890 are your input values for start and stop respectively.
Then you can check it with rowCount or num_rows_affected based on what DB interface you're using (PDO, mysqli, etc.). If it's 0, then no record was inserted, otherwise, the insert occurred.
SQLFiddle Demo
I think this is what you want. This takes two values, $start and $stop, and only does the insert if it does not exist in table2:
insert into table1 (start, stop)
select *
from (select $start as start, $stop as stop) t
where not exists (select 1 from table2 where start = $start and stop = $end)
With parameterized values:
INSERT INTO table1 (start, stop)
SELECT a.*
FROM (SELECT ? start, ? stop) a
LEFT JOIN table2 b ON (a.start,a.stop) IN ((b.start,b.stop))
WHERE b.start IS NULL
This works but we do the insert through SQL statements.
Now, what would be the solution to insert the records by Interface? That is without SQL statement, with the restriction proposed in the problem.