I'm sorry to ask such a basic question, but I cant for the life of me spot the error here as far as I can see everything is correct. Yet I get the error, perhaps I need a pair of fresh eyes to have a look
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 'WHERE event_id = '1243'' at line 1 in INSERT INTO expiredEvents
(event_id,sport_type,tournament,round,team1,team2,venue,event_date)
values ('1243','Rugby','Super15','3','Waratahs','Sharks','Allianz
Stadium','') WHERE event_id = '1243'
$sql="INSERT INTO expiredEvents
(event_id,sport_type,tournament,round,team1,team2,venue,event_date)
values ('$id','$sport','$trnmnt','$rnd','$t1','$t2','$ven','$eDate')
WHERE event_id = '$id'"
There is no WHERE clause in the correct syntax of the INSERT statement.
Depending on what you want to achieve, choose one of the following.
Insert a new row, don't bother if another one having the same event_id already exists
INSERT INTO expiredEvents
(event_id, sport_type, tournament, round, team1, team2, venue, event_date)
VALUES
('$id', '$sport', '$trnmnt', '$rnd', '$t1', '$t2', '$ven', '$eDate')
If event_id is an UNIQUE INDEX of table expiredEvents, this query fails if another record having event_id = '$id' already exists.
Assuming event_id is the PK of the table, keep reading.
Insert a new row but only if it does not already exists
INSERT IGNORE INTO expiredEvents
(event_id, sport_type, tournament, round, team1, team2, venue, event_date)
VALUES
('$id', '$sport', '$trnmnt', '$rnd', '$t1', '$t2', '$ven', '$eDate')
The IGNORE keyword turns the errors into warnings and the query completes successfully but it does not insert the row if another one having event_id = '$id' already exists.
Inserts a row if it does not exist or update the existing one, if it exists
INSERT INTO expiredEvents
(event_id, sport_type, tournament, round, team1, team2, venue, event_date)
VALUES
('$id', '$sport', '$trnmnt', '$rnd', '$t1', '$t2', '$ven', '$eDate')
ON DUPLICATE KEY UPDATE
sport_type=VALUES(sport_type), round=round+1, event_date=NOW()
If the row does not exist, this query insert it using the values from the VALUES clause. If the row already exists then it uses the ON DUPLICATE KEY UPDATE to know how to update it. There are three fields modified in this query:
sport_type=VALUES(sport_type) - the value of column sport_type is updated using the value provided in the query for column sport_type (VALUES(sport_type), which is '$sport');
round=VALUES(round)+1 - the value of column round is updated using its current value plus 1 (round+1); the value provided in the VALUES clause is not used;
event_date=NOW() - the value of column event_date is modified using the value returned by the function NOW(); both the old value and the one provided in the VALUES clause of the query are ignored.
This is just an example, you put there whatever expressions you need to update the existing row.
Completely replace the existing row with a new one
REPLACE INTO expiredEvents
(event_id, sport_type, tournament, round, team1, team2, venue, event_date)
VALUES
('$id', '$sport', '$trnmnt', '$rnd', '$t1', '$t2', '$ven', '$eDate')
The REPLACE statement is a MySQL extension to the SQL standard. It first DELETEs the row having event_id = '$id' (if any) then INSERTs a new row. It is functionally equivalent with DELETE FROM expiredEvents WHERE event_id = '$id' followed by the first query exposed above in this answer.
WHERE keyword is not allowed in INSERT INTO / VALUES
http://dev.mysql.com/doc/refman/5.6/en/insert.html
Elaborate what you would like to accomplish.
Don't use where in insert statment, instead of just get the data from the respective tables which contains the exact records and insert necessary rows alone by adding your conditions in the select statement of that query.
Here is the simple one to resolve your error,
$sql="INSERT INTO expiredEvents
(event_id,sport_type,tournament,round,team1,team2,venue,event_date)
SELECT event_id,sport_type,tournament,round,team1,team2,venue,event_date from events WHERE event_id = '$id'"
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
Let's say I have two columns member_id, email in one table users. I'm trying to add a new row if no similar data is found with below statement:
INSERT INTO users(member_id, email)
VALUES (1,'k#live.com')
WHERE NOT EXISTS (SELECT * FROM users WHERE member_id=1 AND email='k#live.com');
However, it's not working. #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 'WHERE EXISTS
Please shed some light. Thanks.
Assuming you have a unique constraint on member_id, email or a combination of both, I believe you will be better served with an INSERT IGNORE, if the record doesn't exist, it will be inserted.
INSERT IGNORE INTO users(member_id, email)
values (1, 'k#live.com');
If there is no unique constraint, use this technique here
INSERT INTO users(member_id, email)
SELECT 1,'k#live.com'
FROM dual
WHERE NOT EXISTS
(SELECT * FROM users WHERE member_id=1 AND email='k#live.com');
Dual is used in the dummy select rather than users in order to limit the rows inserted to 1.
There cannot be a WHERE clause in an INSERT ... VALUES ... statement.
The normal pattern for avoiding duplicates is to add UNIQUE constraint(s).
If you want to avoid adding any duplicate "member_id" values, and you also want to avoid adding any duplicate "email" values, then
CREATE UNIQUE INDEX mytab_UX1 ON mytab (member_id);
CREATE UNIQUE INDEX mytab_UX2 ON mytab (email);
Whenever an INSERT or UPDATE attempts to create a duplicate value, a duplicate key exception (error) will be thrown. MySQL provides the IGNORE keyword which will suppress the error, and allow the statement to complete successfully, but without introducing any duplicates.
Given an empty table, the first statement would insert a row, the second and third statements would not.
INSERT IGNORE INTO mytab (member_id, email) VALUES (1,'k#live.com');
INSERT IGNORE INTO mytab (member_id, email) VALUES (2,'k#live.com');
INSERT IGNORE INTO mytab (member_id, email) VALUES (1,'aaa#bbb.com');
If you want to restrict just the combination of the two columns to being unique, that is you would allow the 2nd and 3rd statements to insert a row, then you'd add a UNIQUE constraint on the combination of the two columns, rather than two separate unique indexes as above.
CREATE UNIQUE INDEX mytab_UX1 on mytab (member_id, email);
Aside from that convention, say you don't have a unique constraint, but you only want to modify the behavior of the single insert statement, then you can use a SELECT statement to return the values you want to insert, and then you can add a WHERE clause to the SELECT.
To avoid adding any duplicate member_id or duplicate email, then something like this would accomplish that:
INSERT INTO mytab (member_id, email)
SELECT s.member_id, s.email
FROM (SELECT 1 AS member_id, 'k#live.com' AS email) s
WHERE NOT EXISTS (SELECT 1 FROM mytab d WHERE d.member_id = s.member_id)
AND NOT EXISTS (SELECT 1 FROM mytab e WHERE e.email = s.email)
For best performance with a large table, you're going to want at least two indexes, one with a leading column of member_id, and one with a leading column of email. The NOT EXISTS subqueries can make use of an index to quickly locate a "matching" row, rather than scanning every row in the table.)
Again, if it's just the combination of the two columns you want to be unique, you'd use a single NOT EXISTS subquery, as in your original query.
Alternatively, you could use an anti-join pattern as an equivalent to the NOT EXISTS subquery.
INSERT INTO mytab (member_id, email)
SELECT s.member_id, s.email
FROM (SELECT 2 AS member_id, 'k#live.com' AS email) s
LEFT
JOIN mytab d
ON d.member_id = s.member_id
LEFT
JOIN mytab e
ON e.email = s.email
WHERE d.member_id IS NULL
AND e.email IS NULL
Im trying to insert 'testing' into my MeetingNotes column under two conditions but for the life of me I cannot get it to work. Is it possible to do this? I am a beginner with sql and mysql? Thanks in advance!
SELECT MeetingNotes
FROM Meeting
INSERT INTO MeetingNotes
VALUES ('testing')
WHERE MeetingProcessId = '1001' AND MeetingId = '25'
You want to use an UPDATE query, which changes values in existing records. An INSERT query strictly adds new records.
UPDATE Meeting
SET MeetingNotes = 'testing'
WHERE MeetingProcessId = '1001' AND MeetingId = '25'
For future reference, I'm not sure why you have a SELECT statement in your example: it isn't needed to insert or update records. Inserting a new record into the Meeting table (given only the three columns shown) would look like this:
INSERT INTO Meeting (MeetingId, MeetingProcessId, MeetingNotes)
VALUES ('25', '1001', 'Notes about this very exciting meeting...')
A couple notes on this:
Since INSERT statements add an entirely new record to the table, columnwise constraints can't be applied, so they don't support a WHERE clause
If MeetingId is an auto-incrementing record ID generated by the database, it should be / must be left out of INSERT statements
Only string (CHAR/VARCHAR) values should be quoted when they appear in queries, numeric values should not. So if, for example, MeetingId and MeetingProcessId are integer instead of string columns, the quote-marks around 25 and 1001 in the queries above should be removed
What you want is probably:
UPDATE Meeting SET MeetingNotes='testing' WHERE MeetingProcessID = '1001' AND MeetingId = '25';
I tried to insert from one table into another and im having with the redundancy..
I came up with a query but every time when i execute it, It cannot deals with duplicate.
here's my query...
INSERT INTO balik ( balik_date, balik_time, balik_cardID, balik_status,balik_type)
select current_date(), '00:00:00', L_CardID, 'BELUM BALIK', L_Type
FROM logdetail t1
LEFT JOIN balik t2 ON (t1.L_CardID = t2.balik_cardID)
WHERE t1.L_Type = 'IN'
any help will be greatly appreciated
Use INSERT IGNORE instant of INSERT.
Use INSERT IGNORE rather than INSERT. If a record doesn't duplicate an
existing record, MySQL inserts it as usual. If the record is a
duplicate, the IGNORE keyword tells MySQL to discard it silently
without generating an error.
OR
Check row count for unique field. If row exist don't insert or update.
OR
Use REPLACE rather than INSERT. If the record is new, it's inserted
just as with INSERT. If it's a duplicate, the new record replaces the
old one:
Source for definitions MySQL Handling Duplicates
I have a table with columns record_id (auto inc), sender, sent_time and status.
In case there isn't any record of a particular sender, for example "sender1", I have to INSERT a new record otherwise I have to UPDATE the existing record which belongs to "user1".
So if there isn't any record already stored, I would execute
# record_id is AUTO_INCREMENT field
INSERT INTO messages (sender, sent_time, status)
VALUES (#sender, time, #status)
Otherwise I would execute UPDATE statement.
Anyway.. does anyone know how to combine these two statements in order to insert a new record if there isn't any record where the field sender value is "user1" otherwise update the existing record?
MySQL supports the insert-on-duplicate syntax, f.e.:
INSERT INTO table (key,col1) VALUES (1,2)
ON DUPLICATE KEY UPDATE col1 = 2;
If you have solid constraints on the table, then you can also use the REPLACE INTO for that. Here's a cite from MySQL:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.
The syntax is basically the same as INSERT INTO, just replace INSERT by REPLACE.
INSERT INTO messages (sender, sent_time, status) VALUES (#sender, time, #status)
would then be
REPLACE INTO messages (sender, sent_time, status) VALUES (#sender, time, #status)
Note that this is a MySQL-specific command which doesn't occur in other DB's, so keep portability in mind.
As others have mentioned, you should use "insert...on duplicate key update", sometimes referred to as an "upsert". However, in your specific case you don't want to use a static value in the update, but rather the values you pass in to the values clause of the insert statement.
Specifically, I think you want to update two columns if the row already exists:
1) sent_time
2) status
In order to do this, you would use an "upsert" statement like this (using your example):
INSERT INTO messages (sender, sent_time, status)
VALUES (#sender, time, #status)
ON DUPLICATE KEY UPDATE
sent_time = values(sent_time),
status = values(status);
Check out "Insert on Duplicate Key Update".
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;
One options is using on duplicate update syntax
http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html
Other options is doing select to figure out if record exists and then doind inser/update accordingly. Mind that if you're withing transaction select will not explicitly terminate the transaction so it's safe using it.
use merge statement :
merge into T1
using T2
on (T1.ID = T2.ID)
when matched
then update set
T1.Name = T2.Name
when not matched
then insert values (T2.ID,T2.Name);