PDO插入重复键更新

时间:2011-06-03 18:29:43

标签: php parameters insert pdo

发布此问题后MySQL update or insert or die query我已更改为使用PDO但我在使用重复密钥更新短语时遇到了一些问题。

这是我的数组数据的一个例子

array(114) {
["fname"]=>
string(6) "Bryana"
["lname"]=>
string(6) "Greene"
["m080"]=>
string(1) "c"
["t080"]=>
string(1) "-"
["w080"]=>
string(1) "-"
["r080"]=>
["notes"]=>
string(4) "yoyo"}

实际上有113个领域,但我不想浪费在这里展示它们的空间。我正在尝试通过以下代码插入/更新我的数据库

try {
    $dbh = new PDO('login info here');
    $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
    $stmt = $dbh->prepare(
        'INSERT INTO fhours ('.implode(",", array_keys($faculty)).')'.
        ' VALUES (:'.implode(",:", array_keys($faculty)).')'.
        ' ON DUPLICATE KEY UPDATE :fieldlist');

    $stmt->bindParam(':field_list', $field_list);

    foreach($faculty as $key=>$val){
        $stmt->bindParam(':'.$key, $val);
        $fields[] = sprintf("%s = :%s", $key, $key);
    }
    $field_list = join(',', $fields);
    //echo $stmt->debugDumpParams();
    $stmt->execute();
}
catch(PDOException $e){
    echo $e->getMessage();
    exit(); 
}

我收到了无效参数号:参数未定义错误消息。我很确定我的问题在于ON DUPLICATE KEY UPDATE :fieldlist');,但我做了很多不同的尝试,但没有一个有效。我应该再使用ON DUPLICATE KEY UPDATE了吗?

另外,我是:和:: syntax的新手,:name意味着它是一个类似于$name的命名变量,PDOStatement::bindValue类似于PDOStatement->bindValue }?

修改

在回复下面的前两条评论时,我已经更新了代码(但仍无济于事,debugDumpParams说我没有参数)。另外,为什么在$array_of_parameters$faculty成为完全相同的数组时创建 //grab form data $faculty = $_POST; $fname = $_POST['fname']; $lname = $_POST['lname']; //delete the submit button from array unset($faculty['submit']); $array_of_parameters = array(); foreach($faculty as $key=>$val){ $array_of_parameters[$key] = $val; $fields[] = sprintf("%s=?", $key); } $field_list = join(',', $fields); try { $dbh = new PDO('mysql:host=localhost;dbname=kiosk', 'kiosk', 'K10$k'); $dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); $update = 'UPDATE fhours SET '.$field_list. 'WHERE fname="'.$fname.'" AND '. 'lname="'.$lname.'"'; $stmt = $dbh->prepare($update); //echo $stmt->debugDumpParams(); $stmt->execute(array($array_of_parameters)); if($stmt->rowCount() == 0){ $insert = 'INSERT INTO fhours ('.implode(",", array_keys($faculty)).')'. ' VALUES (:'.implode(",:", array_keys($faculty)).')'; $stmt = $dbh->prepare($insert); $stmt->execute(array($array_of_parameters)); } } catch(PDOException $e){ echo $e->getMessage(); exit(); } $dbh=null;

{{1}}

2 个答案:

答案 0 :(得分:2)

以冒号为前缀的名称只不过是命名占位符。当您绑定params时,只需将占位符绑定到某个任意值即可。

ON DUPLICATE KEY UPDATE不是多DBMS友好,但如果你连接到兼容的数据库它应该工作(因为我不相信PDO会阻止所有这些,但我可能是错的)。我不会仅仅为了便携而使用它。你可能想检查你如何绑定你的字段列表,bindparam应该只做一个参数,而那些是colums,不应该像值那样引用(绑定param会这样做)。

我通过运行最多两个查询来设计upsert:更新然后插入。我将首先更新并检查更新的行数是否大于0.如果受影响的行为0,请运行Insert。

只是空闲的评论,113个字段很多字段,如果你不小心,你可能会遇到一些表性能

答案 1 :(得分:2)

您尝试做的是动态构建将参数化的SQL字符串。 :paramname参数应该是映射到列值,where子句参数等的单个值。相反,您使用$fields[] = sprintf("%s = :%s", $key, $key);创建了一个:paramname字段的字符串,以便插入查询。这只是在参数化语句中不起作用。

而不是执行ON DUPLICATE KEY UPDATE :fieldlist,您应该在将整个sql字符串传递到prepare()之前构建它。

然后,您可以使用bindParam()的替代语法来传递预期参数值数组,而不是使用execute()方法单独绑定每个方法。它们需要按正确的顺序排列,或者数组键与SQL中的:param参数名称相同。 See the docs for more info and examples.

$array_of_parameters = array();
foreach($faculty as $key=>$val){
    $array_of_parameters[$key] = $val);
}
$stmt->execute($array_of_parameters);

编辑要在UPDATE语句中正确使用参数,请执行以下操作:

// Create your $field_list before attempting to create the SQL statement
$field_list = join(',', $fields);

$update = 'UPDATE fhours SET '.$field_list. 'WHERE fname=:fname AND lname=:lname';
// Here, echo out $update to make sure it looks correct

// Then add the fname and lname parameters onto your array of params
$array_of_parameters[] = $_POST['fname'];
$array_of_parameters[] = $_POST['lname'];

// Now that your parameters array includes all the faculty in the correct order and the fname & lname,
// you can execute it.
$stmt->prepare($update);
$stmt->execute($array_of_parameters);