'MySQL 8 syntax error INSERT ON DUPLICATE KEY
So, I have this query :
INSERT INTO availabilities (user_id, date, type, available, updated_at, created_at)
VALUES (?, ?, ?, ?, ?, ?),
(?, ?, ?, ?, ?, ?),
(?, ?, ?, ?, ?, ?) AS new
ON DUPLICATE KEY UPDATE available = new.available
I don't see anything wrong here as I'm using the same syntax as this example in the official MySQL documentation :
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new
ON DUPLICATE KEY UPDATE c = new.a+new.b;
Unfortunately, I'm facing this error :
Syntax error or access violation: 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 'AS new ON DUPLICATE KEY UPDATE available = new.available' at line 1
What am I missing ?
MySQL version : 8.0.29 (official docker image)
EDIT :
I have been asked to share the code that generates the query so here it is :
/**
* @param array<Availability> $entities
*/
private function addOrUpdate(array $entities): void
{
$connection = $this->_em->getConnection();
$preparedQuery = 'INSERT INTO availabilities (user_id, date, type, available, updated_at, created_at) VALUES ';
$numberOfEntities = count($entities);
for ($i = 0; $i < $numberOfEntities; $i++) {
if ($i > 0) {
$preparedQuery .= ', ';
}
$preparedQuery .= '(?, ?, ?, ?, ?, ?)';
}
$preparedQuery .= ' AS new ON DUPLICATE KEY UPDATE available = new.available';
$stmt = $connection->prepare($preparedQuery);
$creationDate = CarbonImmutable::create()->toDateTimeString();
for ($i = 0; $i < $numberOfEntities; $i++) {
$entity = $entities[$i];
$offset = $i * 6;
$stmt->bindValue($offset + 1, $entity->getUser()->getId());
$stmt->bindValue($offset + 2, $entity->getDate()->format('Y-m-d'));
$stmt->bindValue($offset+ 3, $entity->getType(), ParameterType::INTEGER);
$stmt->bindValue($offset + 4, $entity->getAvailable(), ParameterType::BOOLEAN);
$stmt->bindValue($offset + 5, $creationDate);
$stmt->bindValue($offset + 6, $creationDate);
}
$stmt->executeStatement();
$this->_em->flush();
}
This is a method from a Doctrine repository in a Symfony (PHP) project.
Here is the table structure :
CREATE TABLE `availabilities` (
`id` int NOT NULL AUTO_INCREMENT,
`user_id` int NOT NULL,
`date` date NOT NULL COMMENT '(DC2Type:date_immutable)',
`type` smallint NOT NULL,
`available` tinyint(1) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_AVAILABILITY_TYPE_DATE` (`user_id`,`type`,`date`),
KEY `IDX_D7FC41EFA76ED395` (`user_id`),
CONSTRAINT `FK_D7FC41EFA76ED395` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=164 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
EDIT 2 :
So, like everyone has suggested, this is the SQL query generated :
INSERT INTO availabilities (user_id, date, type, available, updated_at, created_at)
VALUES AS new
ON DUPLICATE KEY UPDATE available = new.available
Here is the problem : the values are gone ! Maybe I'm doing something wrong with doctrine.
Solution 1:[1]
The example query and the query you provided(without ?) worked fine on my MySQL 8.0.25 version;
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.25 |
+-----------+
1 row in set (0.00 sec)
mysql> INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new ON DUPLICATE KEY UPDATE c = new.a+new.b;
Query OK, 2 rows affected (0.07 sec)
Records: 2 Duplicates: 0 Warnings: 0
Your query replacing ? with values.
mysql> show create table availabilities;
CREATE TABLE `availabilities` (
`user_id` int DEFAULT NULL,
`date` date DEFAULT NULL,
`type` int DEFAULT NULL,
`available` varchar(5) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`created_at` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql> INSERT INTO availabilities (user_id, date, type, available, updated_at, created_at)
-> VALUES (1,'2022-05-10', 1,'Yes','2022-05-10 10:10:10', '2022-05-10 10:10:10'), (2,'2022-05-10', 2,'Yes','2022-05-10 10:10:10', '2022-05-10 10:10:10'), (1,'2022-05-10', 1,'Yes','2022-05-10 10:10:10', '2022-05-10 10:10:10') AS new ON DUPLICATE KEY UPDATE available = new.available ;
Query OK, 3 rows affected (0.05 sec)
Records: 3 Duplicates: 0 Warnings: 0
You have to print the query with values to check the problem
Solution 2:[2]
It was all my fault, I was calling my method with an empty array and was looking at my query syntax when it was my code which was not ok.
Thanks everyone for your help !
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ergest Basha |
| Solution 2 | Romain Ciaccafava |
