MySQL使用批量插入准备语句

时间:2015-07-22 21:07:42

标签: php mysql

我有一个模块,允许管理员将一些用户(可能是多个)添加到组中。

PHP

$user_id  = $_POST["user_id"]; //this can be an array
$group_id = $_POST["group_id"];

$sql = "INSERT IGNORE INTO users_groups (user_id, group_id) 
        VALUES ($user_id[0],$group_id)";

for ( $i = 1; $i < count($user_id); $i++) 
{
    $sql .= ", ($user_id[$i],$group_id)"
}

正如您所看到的,sql-query取决于管理员选择了多少用户。

如何将此代码与预准备语句一起使用,因为后变量来自用户(SQL注入......)

更新

我有两个选择框:

  • 一个用于用户选择(可以进行多项选择 - &gt;数组):$_POST["user_id"]
  • 一个用于组选择(只能进行一次选择):$_POST["group_id"]

现在我想要一个准备好的SQL语句,用于将user_idgroup_id插入到多对多表(users_groups)。问题是必须插入的值的数量可以更改(取决于管理员在选择框中选择了多少用户)。

我想根据管理员选择的用户数量来更改准备好的查询。

例如:

  • 管理员选择了两个用户 - &gt; sql:INSERT IGNORE INTO users_groups (user_id, group_id) VALUES ($user_id[0],$group_id), ($user_id[1],$group_id)
  • 管理员选择了四个用户 - &gt; sql:INSERT IGNORE INTO users_groups (user_id, group_id) VALUES ($user_id[0],$group_id), ($user_id[1],$group_id), ($user_id[2],$group_id), ($user_id[3],$group_id)

我的问题:我怎么能自动完成这个并使用准备好的sql语句,因为我不希望有10次if(count($user_id) == number) {...

更新2 如果我手动执行此操作,代码将如下所示:

$sql = $db->prepare("INSERT IGNORE INTO users_groups (user_id, group_id) VALUES (?, ?)"); 
$sql->bind_param('ii', $user_id[0], $group_id);

更新3 检查post变量中是否只有整数:

$user_id = filter_input_array(INPUT_POST, 'user_id', FILTER_SANITIZE_NUMBER_INT);
$user_id = abs($user_id);

$group_id = filter_input(INPUT_POST, 'group_id', FILTER_SANITIZE_NUMBER_INT);
$group_id = abs($group_id);

1 个答案:

答案 0 :(得分:2)

要创建SQL语句,您可以使用它来生成所有user_id值所需的占位符。

$user_ids  = $_POST["user_id"]; //this can be an array
$group_id = $_POST["group_id"];
$placeholders = implode(', ', array_fill(0, count($user_ids), "(?, ?)"));    
$sql = "INSERT IGNORE INTO users_groups (user_id, group_id) VALUES $placeholders";

然后绑定值,如果你使用pdo,这样的东西应该可以工作:

$stmt = $pdo->prepare($sql);
$i = 1;
foreach ($user_ids as $user_id) {
    $stmt->bindValue($i++, $user_id);
    $stmt->bindValue($i++, $group_id);
}

或者,如果你使用的是mysqli,你可以尝试使用反射这种方法(取自php docs here中的用户注释),注释确实说明这需要PHP 5.3+,希望你有。

$stmt = $mysqli->prepare($sql);
$values[] = str_repeat('ii', count($user_ids));
foreach ($user_ids as $user_id) {
    $values[] = $user_id;
    $values[] = $group_id;
}
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($stmt, $values);
$stmt->execute(); 

或者,因为我顽固而且来自php docs用户注释的内容似乎无法正常工作,经过阅读后我不知道它是如何工作的,考虑到php doc ReflectionMethod::invokeArgs特别说

  

注意:如果函数的参数需要引用,那么它们必须是传递的参数列表中的引用。

然后使用call_user_func_array可能会有效。

$stmt = $mysqli->prepare($sql);
$type = str_repeat('ii', count($user_ids));
foreach ($user_ids as $user_id) {
    $values[] = $user_id;
    $values[] = $group_id;
}
foreach ($values as $key => $value) {
    $value_references[$key] = &$values[$key];
}
call_user_func_array('mysqli_stmt_bind_param', 
    array_merge(array($stmt, $type), $value_references));
但是多么痛苦。我真的很喜欢pdo。

相关问题