2016-10-07 25 views
1

我正在做一些清理和数据转换(该部分完成,哇),并需要将其插入到MySQL表中。之前在Perl中完成了这种事情之后,我认为,作为处理的一部分,将数据作为关联数组来构造是有意义的,关键字与我需要将它们加载到的字段名相同 - 这样一来,只需循环遍历键并生成一个既有名称占位符又有匹配值的列表,就可以轻松构建一条准备好的语句。将PHP关联数组映射到PDO准备语句

但是,我似乎无法在PHP/PDO中完成这项工作。测试代码:

$x = <<<EOD 
1 1 1 1 1 
2 2 2 2 2 
3 3 3 3 3 
4 4 4 4 4 
EOD; 

$fields = array('name', 'job', 'wallet_size', 'inseam', 'pet_name'); 
foreach(explode("\n", $x) as $line){ 
    $data = array_combine($fields, explode(' ', $line)); 

    # print_r($data); 

    $stmt = $dbh->prepare('INSERT INTO foobar VALUES('.':'.implode(', :', $fields)); 

    foreach($fields as $field){ 
     $stmt->bindParam(':'.$field, $data[$field]); 
    } 
    $stmt->execute(); 
} 

坦率地说,感觉太...粗俗和哈克工作 - 而事实并非如此。

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1' in tst.php:24 

这样做正确的方式,正确的?如果有人会向我介绍适合它的PHP风格的措辞,我会很感激。

+3

是否尝试打印“'INSERT INTO foobar VALUES('。':'。implode(',:',$ fields)'?看起来你只是错过了关闭”)“''INSERT INTO foobar VALUES ('。':'。implode(',:',$ fields)。')'' –

+0

@E_p - 干得好!我*做了*回应 - “内部”部分,而不是整个事情 - 它看起来不错。你是对的,这是最后的结果。 –

回答

3

当您盯着格式化SQL的PHP​​代码而不是最终的SQL字符串本身时,很难调试SQL。我建议你总是创建一个字符串变量,以便在调试过程中输出它。

$sql = 'INSERT INTO foobar VALUES('.':'.implode(', :', $fields); 
echo "$sql\n"; 
$stmt = $dbh->prepare($sql); 

输出:

INSERT INTO foobar VALUES(:name, :job, :wallet_size, :inseam, :pet_name 

现在是很容易看到,你忘了关闭)在那个INSERT语句的结束!

另外,您对PDO的使用比它需要的更困难。您不需要使用命名参数。你不需要使用bindParam()。以下是我会写这样的代码:

$fields = array('name', 'job', 'wallet_size', 'inseam', 'pet_name'); 

$columns = implode(',', $fields); 
$placeholders = implode(',', array_fill(1, count($fields), '?')); 
$sql = "INSERT INTO foobar ($columns) VALUES ($placeholders)"; 
echo "$sql\n"; // use this during debugging 
$stmt = $dbh->prepare($sql); 

foreach(explode("\n", $x) as $line){ 
    $param_values = explode(' ', $line); 
    $stmt->execute($param_values); 
} 

提示:

  • 准备查询一次,并重新使用准备好的语句要插入的每一行数据。
  • 将一组数据值作为参数传递给​​。这比使用bindParam()更容易。
  • 当数据位于简单数组而非关联数组中时,使用位置参数占位符(?)而不是命名参数占位符。
+1

美丽 - 我正在寻找。谢谢比尔! @E_p发现了一个事实,即我错过了这个问题,但是你的回答中包含了一些当你阅读它的时候有意义的东西(我的代码没有,在我看来)。非常感谢! –

+0

当你展开某些完美的答案(没有信用)时,确保它是完美的。 '$ sql =“INSERT INTO foobar($ columns)VALUES($ placeholders)”;'应该是'$ sql = sprintf(“INSERT INTO foobar(%s)VALUES(%s)”,$ columns,$ placeholders); ' –

+0

我会同意重写比尔。但是,使用指定的占位符比“?”更容易跟踪。我同时使用MySQLi_和PDO准备的语句,但在PDO中99%的时间使用了命名占位符;但这只是我;-) –