eze*_*ero 13 php mysql pdo prepared-statement
我想知道是否可以使用一个预准备语句插入多行.下面是我通常如何在db中插入一行的示例:
$params=array();
$params[':val1']="val1";
$params[':val2']="val2";
$params[':val3']="val3";
$sql="INSERT INTO table VALUES (col1,col2,col3) VALUES (:val1,:val2,:val3)";
$stmt=DB::getInstance()->prepare($sql);
$stmt->execute($params);
Run Code Online (Sandbox Code Playgroud)
我想插入的值将来自一个数组,例如:$ values [0] ['val1']; $值[0] [ 'val2的']; $值[0] [ 'VAL3']; $值[1] [ 'VAL1']; $值[2] [ 'val2的'];
等等
这段代码可能必须一次插入几百行,我想创建一个循环来创建数百个参数,然后为每行附加一个额外插入的sql语句,但我认为必须有更好的方法.最好的方法是什么?
Jus*_*man 26
首先要说的是,由于只有一个查询,您可以插入多行 INSERT
INSERT INTO Table (col1, col2, col3)
VALUES ('abc', 'def', 'ghi'),
('abc', 'def', 'ghi'),
('abc', 'def', 'ghi'),
('abc', 'def', 'ghi'),
('abc', 'def', 'ghi')
-- and so on...
Run Code Online (Sandbox Code Playgroud)
一旦你知道了,你就可以通过PDO获得一个很好的解决方案(例如).
你必须保持你想要一个完整的头脑prepare和execute过程(在安全期限,你必须单独通过每个参数).
假设您有要插入结构的行,如下所示:
$rows = array(
array('abc', 'def', 'ghi'), // row 1 to insert
array('abc', 'def', 'ghi'), // row 2 to insert
array('abc', 'def', 'ghi') // row 3 to insert
// and so on ...
);
Run Code Online (Sandbox Code Playgroud)
您的目标是将此结果作为准备好的查询:
INSERT INTO Table (col1, col2, col3)
VALUES (?, ?, ?),
(?, ?, ?),
(?, ?, ?)
Run Code Online (Sandbox Code Playgroud)
与其相应的执行:
PDOStatement::execute(array('abc', 'def', 'ghi', 'abc', 'def', 'ghi', 'abc', 'def', 'ghi'));
Run Code Online (Sandbox Code Playgroud)
好吧,你现在只需要这样做:
$rows = array(
array('abc', 'def', 'ghi'),
array('abc', 'def', 'ghi'),
array('abc', 'def', 'ghi')
);
$row_length = count($rows[0]);
$nb_rows = count($rows);
$length = $nb_rows * $row_length;
/* Fill in chunks with '?' and separate them by group of $row_length */
$args = implode(',', array_map(
function($el) { return '('.implode(',', $el).')'; },
array_chunk(array_fill(0, $length, '?'), $row_length)
));
$params = array();
foreach($rows as $row)
{
foreach($row as $value)
{
$params[] = $value;
}
}
$query = "INSERT INTO Table (col1, col2, col3) VALUES ".$args;
$stmt = DB::getInstance()->prepare($query);
$stmt->execute($params);
Run Code Online (Sandbox Code Playgroud)
而且......就是这样!
这样,每个param都是单独处理的,这是你想要的(安全性,安全性,安全性!)和所有这些,只需一个INSERT查询的动态方式
如果要插入太多行(请参阅此内容),则应execute逐个插入
$rows = array(
array('abc', 'def', 'ghi'), // row 1 to insert
array('abc', 'def', 'ghi'), // row 2 to insert
array('abc', 'def', 'ghi') // row 3 to insert
// and so on ...
);
$args = array_fill(0, count($rows[0]), '?');
$query = "INSERT INTO Table (col1, col2, col3) VALUES (".implode(',', $args).")";
$stmt = $pdo->prepare($query);
foreach ($rows as $row)
{
$stmt->execute($row);
}
Run Code Online (Sandbox Code Playgroud)
如果你只插入几百行,我会喜欢更简单的代码,如下所示.准备单行INSERT语句,然后遍历数据数组,为每一行执行一次准备好的查询.
$rows = array(
array('abc', 'def', 'ghi'), // row 1 to insert
array('abc', 'def', 'ghi'), // row 2 to insert
array('abc', 'def', 'ghi') // row 3 to insert
// and so on ...
);
$params = implode(",", array_fill(0, count($rows[0]), "?"));
$sql = "INSERT INTO mytable VALUES ($params)";
$stmt = $pdo->prepare($sql); // rely on exceptions for error detection
foreach ($rows as $row) {
$stmt->execute($row);
}
Run Code Online (Sandbox Code Playgroud)
MySQL当然支持多行INSERT语法,因此您可以尝试将它们放在一起.
$params = implode(",", array_fill(0, count($rows[0]), "?"));
$tuples = "(" . implode("),(", array_fill(0, count($rows), $params)) . ")";
$sql = "INSERT INTO mytable VALUES $tuples";
$values = call_user_func_array("array_merge", $rows);
$stmt = $pdo->prepare($sql);
$stmt->execute($values);
Run Code Online (Sandbox Code Playgroud)
但是,如果您尝试使用与数据数组中的项目一样多的元组创建单个INSERT语句,则可能会意外地生成长度超过最大数据包长度的SQL语句.
如果你有成千上万的行,那么一次执行一行准备好的语句是一个过多的开销,你应该使用LOAD DATA INFILE.
如果您的表是事务性的(例如InnoDB),则可以使用事务来加速插入.交易还具有回滚的优势.
$pdo = DB::getInstance();
$stmt = $pdo->prepare('INSERT INTO table VALUES (col1, col2, col3) VALUES (:val1, :val2, :val3)');
$pdo->beginTransaction();
// The queries are not executed yet, but pushed to a transaction "stack"
foreach ($values as $value) {
$stmt->execute([
':val1' => $value['val1'],
':val2' => $value['val2'],
':val3' => $value['val3'],
]);
}
// Executes all the queries "at once"
$pdo->commit();
Run Code Online (Sandbox Code Playgroud)
为了保留您的代码,您必须创建一个循环来执行您需要的所有插入:
$array_params = array();
$params[':val1']="val1 1";
$params[':val2']="val1 2";
$params[':val3']="val1 3";
$array_params[] = $params;
$params[':val1']="val2 1";
$params[':val2']="val2 2";
$params[':val3']="val2 3";
$array_params[] = $params;
$sql="INSERT INTO table (col1,col2,col3) VALUES (:val1,:val2,:val3)";
$stmt=DB::getInstance()->prepare($sql);
foreach($array_params as $params)
{
$stmt->execute($params);
}
Run Code Online (Sandbox Code Playgroud)
但是可以使用一个查询来执行多次插入INSERT INTO table (col1,col2,col3) VALUES ("val1","val2","val3"),("val4","val5","val6"),("val7","val8,"val9"),例如,通过使用类似这样的东西来构建查询:
$all_inserts = array( array('val1', 'val2', 'val3'),array('val4', 'val5', 'val6'));
$sql = 'INSERT INTO table (col1,col2,col3) VALUES ';
$rows = array();
foreach ($all_inserts as $one_insert)
{
$rows[] = '('.implode(',', $pdo->quote($one_insert).')';
}
$sql .= ' '.implode(',', $rows);
$pdo->query($sql);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
22655 次 |
| 最近记录: |