我正在将应用程序从本机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?
答案 0 :(得分:3)
由于并非所有代码都可用(来自php端),以防您的查询处于某种循环中,因此最快(也许部分)解决方案如下:
$order_id = '22BD24';
$customer_id = 1;
try {
$q = "INSERT INTO `z_many` (`order_id`,`customer_id`,`dateadded`)
VALUES (:order_id,:customer_id,NOW())
ON DUPLICATE KEY UPDATE `dateadded`=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();
}
答案 1 :(得分:1)
我复制了你在我的mysql数据库上提供的SQL模式并添加了脚本代码,但是在开始时使用PDO初始化:
$dbx_pdo = new PDO('mysql:host=127.0.0.1;dbname=test12;charset=utf8','root','');
.. 工作正常,但我的设置是php 5.5.9和mysql 5.6.16
所以我认为你的代码执行了两次,也许它在一个事务内部,所以你得到了回滚。需要了解更多背景
答案 2 :(得分:1)
请删除主键列的默认值。也使用构造
INSERT INTO (`field1`, `field2`, `...`) values (val1, val2, val3);
如果你告诉插入的默认值是什么 - 一些mysql版本在插入时会看到错误。这就是为什么你应该使用自动增量或根本不使用默认值。
答案 3 :(得分:0)
在黑暗中拍摄。我只使用带有ORACLE PL / SQL的PDO和bindParam()。如果它是,15
值,请查看第四个参数PARAM_STR
。所以试试这个,希望它有所帮助。
$stmt->bindParam(':order_id', $order_id, PDO::PARAM_STR, 15);
$stmt->bindParam(':customer_id', $customer_id, PDO::PARAM_INT);
这15表示你表中order_id的(bufffer-)长度。