【发布时间】:2014-12-17 16:05:15
【问题描述】:
我正在将应用程序从本地 mysqli 调用转换为 PDO。尝试将行插入具有外键约束的表时遇到错误。
注意:这是一个简化的测试用例,不应复制/粘贴到生产环境中。
信息 PHP 5.3、MySQL 5.4
首先,这是表格:
CREATE TABLE `z_one` (
`customer_id` int(10) unsigned NOT NULL DEFAULT '0',
`name_last` varchar(255) DEFAULT NULL,
`name_first` varchar(255) DEFAULT NULL,
`dateadded` datetime DEFAULT NULL,
PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `z_one` VALUES (1,'Khan','Ghengis','2014-12-17 10:43:01');
CREATE TABLE `z_many` (
`order_id` varchar(15) NOT NULL DEFAULT '',
`customer_id` int(10) unsigned DEFAULT NULL,
`dateadded` datetime DEFAULT NULL,
PRIMARY KEY (`order_id`),
KEY `order_index` (`customer_id`,`order_id`),
CONSTRAINT `z_many_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `z_one` (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
或者如果你愿意,
mysql> describe z_one;
+-------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| customer_id | int(10) unsigned | NO | PRI | 0 | |
| name_last | varchar(255) | YES | | NULL | |
| name_first | varchar(255) | YES | | NULL | |
| dateadded | datetime | YES | | NULL | |
+-------------+------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> describe z_many;
+-------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| order_id | varchar(15) | NO | PRI | | |
| customer_id | int(10) unsigned | YES | MUL | NULL | |
| dateadded | datetime | YES | | NULL | |
+-------------+------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
接下来,这里是查询:
$order_id = '22BD24';
$customer_id = 1;
try
{
$q = "
INSERT INTO
z_many
(
order_id,
customer_id,
dateadded
)
VALUES
(
:order_id,
:customer_id,
NOW()
)
";
$stmt = $dbx_pdo->prepare($q);
$stmt->bindValue(':order_id', $order_id, PDO::PARAM_STR);
$stmt->bindValue(':customer_id', $customer_id, PDO::PARAM_INT);
$stmt->execute();
} catch(PDOException $err) {
// test case only. do not echo sql errors to end users.
echo $err->getMessage();
}
这会导致以下 PDO 错误:
SQLSTATE[23000]:违反完整性约束:1062 重复条目 键 'PRIMARY' 的 '22BD24'
mysqli 处理相同的查询可以正常工作。当没有找到任何重复项时,为什么 PDO 会拒绝带有“重复条目”消息的 INSERT?
【问题讨论】:
-
您的支票是多余的。除了为主键选择错误的数据类型外,您不必检查是否存在具有特定 id 的订单。你可以插入。如果插入失败,则检查它是否因为违反完整性约束而失败,这意味着具有该 PK 的记录存在。
-
@Pow-lan 那是 SQL DDL,与 PDO 无关。
-
@Pow-lan
KEY和INDEX在 MySQL 中是同义词。在任何情况下,它都不是 unique 约束,因此不太可能与此错误有关。 -
在网络服务器之外运行代码和/或添加一些调试输出(到日志文件,而不是
echo等)。我很确定插入被执行了两次。 -
所以我想对此进行测试并复制 sql 以创建一个表,在 phpmyadmin 中运行它并准确复制代码。添加了一行以创建新的 pdo 连接,其他所有内容都复制/粘贴完全相同。运行页面,它按预期创建了一行,没有错误。刷新并得到与预期相同的完整性约束错误。这是 php 5.4.12 和 mysql 5.6。所以像大多数其他人一样,我会回去检查它是否不止一次运行。该页面是否包含在另一个脚本中?这是在函数中还是从框架中调用?
标签: php mysql pdo foreign-keys foreign-key-relationship