【问题标题】:PDO SQL single query, multiple rows and valuesPDO SQL 单查询,多行多值
【发布时间】:2015-02-10 06:30:09
【问题描述】:

我有这个数组 JSON POST 请求到一个 PHP 文件。

Array
(
[user_id] => 1
[date] => 2014-12-05
[time] => 12:00
[description] => lol
[friends] => "12","9"
[PHPSESSID] => 5ae7c3e6339c528e7804020dd0f0cdbb
)

我尝试使用单个 sql 查询将值 (12 | 1) 和 (9 | 1) 添加到 mysql 表中

表:

u_id  |  f_id
  1   |   12
  1   |   9

到目前为止我所拥有的:

$friendarray = $_POST['Friends'];

foreach( $friends as $friendsarray ) {
    $values[] = "(" . $u_id . "," . $friendsarray . ")";
    }

$query = "INSERT INTO up2_friends_to_users (u_id , f_id ) VALUES ".implode(',',$values);

    $stmt   = $db->prepare($query);
    $result = $stmt->execute();

如您所见,这根本不起作用。我试图实现这样的目标:

$query_params = array(
    ':u_id' => $_POST['user_id'],
    ':f_id' => $friendid,

然后想这样发送:

    $stmt   = $db->prepare($query);
    $result = $stmt->execute($query_params);

是否可以像这样创建具有多行的单个查询?

感谢 RobP 的回答:

        $friendsarray = explode(',',$_POST['friends']);
        $placeholders = [];

        for($i=0, $len=count($friendsarray); $i < $len; $i++) {
            $placeholders[i] .= "(:u_id".$i.", :f_id".$i.")"; // entries like "(:u_id0, :f_id0)"
        }
        $query = "INSERT INTO up2_friends_to_users (u_id , f_id ) VALUES  ".implode(",", $placeholders);
        $stmt = $db->prepare($query);
        for($i=0, $len=count($placeholders); $i < $len; $i++) {
            $stmt->bindParam(':u_id'.$i, $_POST['user_id']);
            $nextFriend = $friendsarray[$i];
            $stmt->bindParam(':f_id'.$i,trim($nextFriend,'"'));
        }
        $result = $stmt->execute(); 

现在 f_id 始终为空。

【问题讨论】:

  • 分配$query时需要先设置$values再使用。
  • 您指定$friendarray,但在foreach 循环中使用$friends
  • 挑战是使用长的 VALUES 列表执行单个 INSERT,但仍将所有这些值作为注入安全的绑定参数。我在下面戳了一下。

标签: php mysql sql arrays json


【解决方案1】:

我同意最好的策略是像您尝试做的那样使用单个查询。这对于长列表会快得多,特别是如果您不将所有单独的插入包装到单个提交中。这应该有效:

$friendarray = $_POST['Friends'];
$placeholders = [];
$user_id = $_POST[`user_id`];

for($i=0, $len=count($friendarray); $i < $len; $i++) {
    $placeholders[$i] = "(:u_id".$i.", :f_id".$i.")"; // entries like "(:u_id0, :f_id0)"
}

$query = "INSERT INTO up2_friends_to_users (u_id , f_id ) VALUES ".implode(",", $placeholders);
$stmt = $db->prepare($query);
for($i=0, $len=count($placeholders); $i < $len; $i++) {
    // each binding must use a separate variable, not an array element
    $stmt->bindParam(':u_id'.$i, $user_id);
    // use your favorite escape function on the value here
    $nextFriend = $db->real_escape_string($friendarray[$i]);
    $stmt->bindValue(':f_id'.$i, $nextFriend);
}

编辑:从Only variables can be passed by reference - php 学到了一些新东西。不能将数组元素作为第二个参数传递给 bindParam!上面发布的解决方法。

【讨论】:

  • 错字:$friendsarray 应该是$friendarray
  • 顺便说一句,使用多个 INSERTS 可能是合理的,但前提是被 beginTransaction() 和 commit() 调用包围。在一个令人难忘的场合,我的表现非常糟糕,原因是每次写入的所有交易。
  • 代码似乎可以工作,但我的表中没有看到任何条目。我将在上面编辑我的帖子。
  • @Konter 我错过了第一个 bindParam 的括号。你能输出/检查 $query 字符串吗?
  • 我又发现了两个错别字,在 [i].= 中缺少 $,这两个错误都应该在 for 循环内的行中更改为 =。在 phpfiddle 中测试,它可以工作。
【解决方案2】:

这样做:

$query = "INSERT INTO up2_friends_to_users (u_id , f_id ) VALUES (:u_id, :f_id)";
$stmt = $db->prepare($query);
$stmt->bindParam(':u_id', $_POST['user_id'];
$stmt->bindParam(':f_id', $friendid);

foreach ($_POST['Friends'] as $friendid) {
    $stmt->execute();
};

bindParam 绑定到一个引用,因此每次执行查询时,它都会使用当前循环迭代中的$friendid 值。

【讨论】:

  • 您好,谢谢您的回答,但这不会多次执行sql查询而不是一次查询吗?
  • 是的,它会的。除非表格中有数百个朋友,否则没什么大不了的,最好使用准备好的语句。您的代码受到 SQL 注入的影响。
  • 问题是每次 POST 都会有 50 到 100 个好友添加到表中。
  • 我认为这不足以导致性能问题。但是,如果您想在一个查询中执行此操作,我认为您的代码应该可以工作,只要您修复我在评论中提到的变量名称。
  • @Konter 查看我的帖子,因为它在单个 INSERT 中执行并且仍在使用绑定参数。
【解决方案3】:

也许,像这样(使用问号参数)?

$values = array();
foreach ($_POST['Friends'] as $friendid) {
    $values[] = $u_id;
    $values[] = $friendid;
}

$conn = new \PDO($dsn, $user, $password);
$query = 'INSERT INTO up2_friends_to_users (u_id , f_id ) VALUES '
        . trim(str_repeat('(?, ?),', count($values / 2)), ',');
$conn->prepare($query)->execute($values);

【讨论】:

    猜你喜欢
    • 2012-12-29
    • 1970-01-01
    • 2019-10-04
    • 2011-06-11
    • 1970-01-01
    • 2016-03-13
    • 2010-11-13
    相关资源
    最近更新 更多