I'm getting "Duplicate entry" on an insert query that worked fine with the old mysqli functions. Once I converted to PDO, the same insert statement breaks.
Here's the sample SQL data
CREATE TABLE IF NOT EXISTS `lookup_codes` (
`id` int(3) NOT NULL,
`code` varchar(10) NOT NULL,
PRIMARY KEY (`id`,`code`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `lookup_codes` (`id`, `code`) VALUES
(1, 'AR'),
(1, 'CN'),
(1, 'OA'),
(4, 'AR'),
(4, 'OA');
And here is the example php/pdo code. (This is not a code critique request - just trying to boil down a problem to a simple example, do not use this code in production, yada yada).
// posted data from user
$id = 2;
$arr_codes = array('AR','CN');
// make sure existing rows do not exist
try
{
$q = "SELECT COUNT(*) FROM lookup_codes WHERE id=:id";
if ($dbg) { echo "<p>SELECT COUNT(*) FROM lookup_codes WHERE id=$id<br>";}
$stmt = $dbx_pdo->prepare($q);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
list($count_rows) = $stmt->fetch(PDO::FETCH_NUM); $stmt->closeCursor();
if ($count_rows>0)
{
try
{
$q = "DELETE FROM lookup_codes WHERE id=:id";
if ($dbg) { echo "<p>DELETE FROM lookup_codes WHERE id=$id<br>";}
$stmt = $dbx_pdo->prepare($q);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$stmt->closeCursor();
} catch(PDOException $err) {
echo $err->getMessage());
exit;
}
}
} catch(PDOException $err) {
echo $err->getMessage());
exit;
}
// set up prepared statement based on posted data
foreach ($arr_codes as $code)
{
$arr_ip[] = array(
'id' => $id,
'code' => $code,
);
}
$txt_prepared = join(',', array_fill(0, count($arr_ip), '( ?, ?)'));
// try inserting
try
{
$q = "INSERT INTO lookup_codes (id, code) VALUES $txt_prepared";
$stmt = $dbx_pdo->prepare($q);
$cb = 1;
foreach ($arr_ip as $rip)
{
$id = $rip['id'];
$code = $rip['code'];
$stmt->bindParam($cb++, $id, PDO::PARAM_INT);
$stmt->bindParam($cb++, $code, PDO::PARAM_STR);
if ($dbg) { echo "<b>Binding</b> ($id, $code)<br>";}
}
$stmt->execute();
$stmt->closeCursor();
} catch(PDOException $err) {
echo $err->getMessage());
exit;
}
That's all there is on my test script. No header or meta redirects.. just a single run of code here.
The example above results in:
Error: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2-CN' for key 'PRIMARY'
Note that it reports back duplicate on the second submitted code.
The same INSERT
works just fine when using mysqli_query()
. There are no errors written to the error log.
What is going on here?
The problem is the way you are binding on your insert query. You need to change $stmt->bindParam
to $stmt->bindValue
. bindParam takes a variable by reference so on each iteration of your loop as you change the value of $id and $code you are changing the value that was bound. bindValue will take a copy of the value from the variable and bind that instead.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments