PHP 准备好的语句无法分配正确的值
PHP Prepared Statements fails to assign correct values
我想做的是插入多行 key/value 对。条目需要是唯一的(具体的主键)。
语句准备了要插入的值的计数:
$sql = "INSERT INTO `test_values` (`foreignID1`,`value`) VALUES";
for($ix=0;$ix<count($values);$ix++){
if($ix>0){ $sql.= ", ";}
$sql .= "(:parentID,:value$ix)";
}
echo $sql; //INSERT INTO `test_values` (`parentID`,`value`) VALUES (:parentID,:value0), (:parentID,:value1)
然后,在准备语句时我循环值:
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':parentID',$parentID);
foreach($values as $key => $value){
$valName = ":value$key";
var_dump($valName);
var_dump($value);
$stmt->bindParam($valName,$value);
}
转储告诉我每次(正确)分配其他值时:
string(7) ":value0"
string(14) "one.domain.com"
string(7) ":value1"
string(18) "another.domain.com"
仍然,我收到 SQL 错误:
Error: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '18-another.domain.com' for key 'PRIMARY'
我绝对知道这些条目不存在。我高度怀疑 PDOStatement 两次绑定相同的值,但我不知道为什么要这样做。
[编辑]: 建议的答案已实施,新输出:
string(7) ":parent0"
string(14) "18"
string(7) ":value0"
string(14) "one.domain.com"
string(7) ":parent1"
string(14) "18"
string(7) ":value1"
string(18) "another.domain.com"
还是一样的错误。
[EDIT2]: 避免讨论:
INSERT INTO `test_values` (`parentID`,`value`) VALUES ('18','one.domain.com'),('18','another.domain.com')
使用 phpMyAdmin 直接应用于数据库,效果非常好...我担心我的陈述发生的是值设置不正确,结果如下:
INSERT INTO `test_values` (`parentID`,`value`) VALUES ('18','another.domain.com'),('18','another.domain.com')
因为约束总是在 LAST 条目上失败,无论我尝试插入多少。
[EDIT3]:
table结构,如问:
CREATE TABLE IF NOT EXISTS `test_values` (
`foreignID1` int(11) NOT NULL,
`value` varchar(256) NOT NULL,
PRIMARY KEY (`foreignID1`,`value`)
)
[EDIT4]:
有效的是不使用链式插入,而是为每个值使用单个插入:
$sql = "INSERT INTO `test_values` (`foreignID1`,`value`) VALUES (:parendID,:value)";
foreach($values as $key => $value){
$stmt = $dbh->prepare($sql);
$stmt->bindParam(":parendID",$parentID);
$stmt->bindParam(":value",$value);
$stmt->execute();
}
...但这不是问题的实际要点。
改变这个 -
$sql .= "(:parentID,:value$ix)";
对此 -
$sql .= "(:parentID$ix,:value$ix)";
所以你的 parent id 也会增加。
据我所知,您收到的错误表明 PRIMARY KEY
s 组合已经存在于 table 中。你的 table 有 composite primary keys 这意味着,有
PRIMARY KEY (`foreignID1`,`value`)
你可以INSERT
这样的数据
+------------+-------+
| foreignID1 | value | # There are duplicated `foo` values
+------------+-------+ # for column `value` which is ok
| 1 | foo | # because PRIMARY KEY is made of
+------------+-------+ # two columns together,
| 2 | foo | # not each respectively
+------------+-------+
| 3 | bar |
+------------+-------+
虽然这种情况不可能
+------------+-------+
| foreignID1 | value | # First two entries are
+------------+-------+ # a constraint violation.
| 1 | foo | #
+------------+-------+ # Columns `foreignID1` and `value`
| 1 | foo | # create a single PRIMARY KEY
+------------+-------+ # therefore having the same combination
| 2 | bar | # of values in these columns is impossible
+------------+-------+
我终于自己找到了答案:
问题是 foreach 循环,因为 bindParam() 不会复制变量,而是保存对它的引用。执行语句时,将读取值。 foreach 循环完成后,$value 变量将保存 foreach 循环的最后一个值。
要使其正常工作,必须使用 for 循环,否则不能使用该值:
foreach($values as $key => $value){
$stmt->bindParam(":parendID$key",$parentID);
$stmt->bindParam(":value$key",$values[$key]);
}
我想做的是插入多行 key/value 对。条目需要是唯一的(具体的主键)。
语句准备了要插入的值的计数:
$sql = "INSERT INTO `test_values` (`foreignID1`,`value`) VALUES";
for($ix=0;$ix<count($values);$ix++){
if($ix>0){ $sql.= ", ";}
$sql .= "(:parentID,:value$ix)";
}
echo $sql; //INSERT INTO `test_values` (`parentID`,`value`) VALUES (:parentID,:value0), (:parentID,:value1)
然后,在准备语句时我循环值:
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':parentID',$parentID);
foreach($values as $key => $value){
$valName = ":value$key";
var_dump($valName);
var_dump($value);
$stmt->bindParam($valName,$value);
}
转储告诉我每次(正确)分配其他值时:
string(7) ":value0"
string(14) "one.domain.com"
string(7) ":value1"
string(18) "another.domain.com"
仍然,我收到 SQL 错误:
Error: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '18-another.domain.com' for key 'PRIMARY'
我绝对知道这些条目不存在。我高度怀疑 PDOStatement 两次绑定相同的值,但我不知道为什么要这样做。
[编辑]: 建议的答案已实施,新输出:
string(7) ":parent0"
string(14) "18"
string(7) ":value0"
string(14) "one.domain.com"
string(7) ":parent1"
string(14) "18"
string(7) ":value1"
string(18) "another.domain.com"
还是一样的错误。
[EDIT2]: 避免讨论:
INSERT INTO `test_values` (`parentID`,`value`) VALUES ('18','one.domain.com'),('18','another.domain.com')
使用 phpMyAdmin 直接应用于数据库,效果非常好...我担心我的陈述发生的是值设置不正确,结果如下:
INSERT INTO `test_values` (`parentID`,`value`) VALUES ('18','another.domain.com'),('18','another.domain.com')
因为约束总是在 LAST 条目上失败,无论我尝试插入多少。
[EDIT3]:
table结构,如问:
CREATE TABLE IF NOT EXISTS `test_values` (
`foreignID1` int(11) NOT NULL,
`value` varchar(256) NOT NULL,
PRIMARY KEY (`foreignID1`,`value`)
)
[EDIT4]:
有效的是不使用链式插入,而是为每个值使用单个插入:
$sql = "INSERT INTO `test_values` (`foreignID1`,`value`) VALUES (:parendID,:value)";
foreach($values as $key => $value){
$stmt = $dbh->prepare($sql);
$stmt->bindParam(":parendID",$parentID);
$stmt->bindParam(":value",$value);
$stmt->execute();
}
...但这不是问题的实际要点。
改变这个 -
$sql .= "(:parentID,:value$ix)";
对此 -
$sql .= "(:parentID$ix,:value$ix)";
所以你的 parent id 也会增加。
据我所知,您收到的错误表明 PRIMARY KEY
s 组合已经存在于 table 中。你的 table 有 composite primary keys 这意味着,有
PRIMARY KEY (`foreignID1`,`value`)
你可以INSERT
这样的数据
+------------+-------+
| foreignID1 | value | # There are duplicated `foo` values
+------------+-------+ # for column `value` which is ok
| 1 | foo | # because PRIMARY KEY is made of
+------------+-------+ # two columns together,
| 2 | foo | # not each respectively
+------------+-------+
| 3 | bar |
+------------+-------+
虽然这种情况不可能
+------------+-------+
| foreignID1 | value | # First two entries are
+------------+-------+ # a constraint violation.
| 1 | foo | #
+------------+-------+ # Columns `foreignID1` and `value`
| 1 | foo | # create a single PRIMARY KEY
+------------+-------+ # therefore having the same combination
| 2 | bar | # of values in these columns is impossible
+------------+-------+
我终于自己找到了答案:
问题是 foreach 循环,因为 bindParam() 不会复制变量,而是保存对它的引用。执行语句时,将读取值。 foreach 循环完成后,$value 变量将保存 foreach 循环的最后一个值。
要使其正常工作,必须使用 for 循环,否则不能使用该值:
foreach($values as $key => $value){
$stmt->bindParam(":parendID$key",$parentID);
$stmt->bindParam(":value$key",$values[$key]);
}