从数组的一个查询中插入多行[重复]
Posted
技术标签:
【中文标题】从数组的一个查询中插入多行[重复]【英文标题】:inserting multiple rows in one query from an array [duplicate] 【发布时间】:2013-04-29 08:58:13 【问题描述】:我有一个帖子中的数组:
//this are arrays
$name = $_POST["name"];
$age = $_POST["age"];
$date = $_POST["date"];
我在 PDO 中有一个插入查询:
$stmt = $db->prepare("INSERT INTO staff (name, age, address) VALUES (:name, :age, :address)");
我的问题是如何使用 php 生成/或实现查询,如下所示:
INSERT INTO staff (name, age, address) VALUES
($name[0], $age[0], $address[0]), ($name[1], $age[1], $address[1])... etc
我尽量降低服务器负载。
【问题讨论】:
查询的数量实际上并不是产生服务器负载的原因。同样从您的问题来看,您还不清楚您要解决哪个具体问题? IIRC PHP 手册有一个代码示例,它是如何工作的,所以我想知道什么对你不起作用?也许您可以稍微澄清一下您遇到的具体问题? 【参考方案1】:您可以准备适当的声明,例如:
$sql = "INSERT INTO staff (name, age, address) VALUES ";
$values = array();
for ($i = 1; $i <= $count; $i++)
$values[] = "(:name$i, :age$i, :address$i)"
$stmt = $db->prepare($sql . implode(', ', $values));
但是,恕我直言,您可能会很好地遍历每组值。对服务器来说负担不大,你的代码会更简单。
【讨论】:
如果您打开EMULATE_PREPARES
,您将拥有重用已解析语句的优势。
我猜是小错字:age$1, :address$1
我得到无效的参数号:没有绑定参数
+1 表示结尾的句子。这个问题的唯一明智的建议:)
@Viscocent:我有一段时间没用过 pdo,但如果你没记错的话,你需要在传递像 array('name1'=>$name[0], 'age1' => $age[0], ...)
这样的数组时执行。它不漂亮,因此我在最后的建议是:不要打扰这些东西,并发送尽可能多的插入。【参考方案2】:
准备好的语句是不可能的。
如果您想在一个查询中插入可变数量的记录,则必须动态生成 SQL 查询,这使得 无法事先准备。
如果您使用数据库驱动程序的 escape_string
函数(对于 mysql,则为 quote()
),那么您可以构建查询并仍然获得准备好的语句为您提供的安全性。
$query = "INSERT INTO table (a, b, c) VALUES";
$tuple = " ('%s', '%s', '%s'),";
foreach ($items as $item)
$a = $db->quote($item['a']);
$b = $db->quote($item['b']);
$c = $db->quote($item['c']);
$query .= sprintf($tuple, $a, $b, $c);
$query = rtrim($query, ","); // Remove trailing comma
// Use the query...
附录:
如果您使用准备好的语句,那么您可以单独插入记录,而不必担心一次性插入它们。这实际上是准备好的语句的全部意义。
与老式的 SQL 查询不同,后者是一步过程,只是被发送然后被遗忘......
$db->query("INSERT INTO table (a, b, c) VALUES ('a', 'b', 'c')");
...准备好的语句是一个两步过程。
首先,您创建准备好的语句。然后这个语句被发送到数据库,告诉它“这是你应该期待的”。数据库通常还会优化查询以使其更快。然后,此步骤会返回一个语句句柄(在 PHP 文档中通常称为 $stmt
)。
$stmt = $db->prepare('INSERT INTO table (a, b, c) VALUES (:a, :b, :c)');
其次,使用此句柄,您可以继续插入内容:
foreach ($records as $record)
$stmt->execute(array(
':a' => $record['a'],
':b' => $record['b'],
':c' => $record['c'],
));
因为数据库已经知道会发生什么,它可以优化INSERT
s 的速度,这意味着您不必经历我在本附录上面提到的内容。
***实际上有一个 quite nice writeup 的准备好的语句。
【讨论】:
该 escape_string 函数在 PDO 中被称为quote
,它已经在字符串周围加上引号,除了转义特殊字符。
@Sverri 我得到:调用未定义的方法 PDO::escape_string()
@Viscocent 查看 MarcelKorpel 的评论。【参考方案3】:
将 delayed
关键字添加到插入 (insert delayed ...
) 以减少服务器负载,并且只需循环使用所有值的准备好的语句。如果你做了一大堆插入,MySQL 无论如何都会在内部将它作为单独的 insert
语句排队,扩展语法只是语法糖。
【讨论】:
【参考方案4】:如果你使用 PDO,你应该准备你的语句,并用不同的值执行它:
$stmt = $db->prepare("INSERT INTO staff (name,age,address) VALUES (:name,:age,:address)");
for($i=0;$i<count($name);$i++)
$stmt->execute(array(
":name" => $name[$i],
":age" => $age[$i],
":address" => $address[$i]));
但是,如果您想将其放入单个查询中,则应使用 $db->exec():
$query = "INSERT INTO staff (name,age,address) VALUES ";
$values = array();
for($i=0;$i<count($names);$i++)
array_push($values, "('" . $name[$i] . "','" . $age[$i] . "','" . $address . "')");
$db->exec($query . implode("," . $values));
警告此方法与 prepare 和 execute 方法相反,由于它不验证输入而易受攻击
【讨论】:
以上是关于从数组的一个查询中插入多行[重复]的主要内容,如果未能解决你的问题,请参考以下文章