PDO preparado Inserta varias filas en una sola consulta
Actualmente estoy usando este tipo de SQL en MySQL para insertar varias filas de valores en una sola consulta:
INSERT INTO `tbl` (`key1`,`key2`) VALUES ('r1v1','r1v2'),('r2v1','r2v2'),...
En las lecturas sobre PDO, el uso de declaraciones preparadas debería brindarme una mayor seguridad que las consultas estáticas.
Por lo tanto, me gustaría saber si es posible generar "insertar varias filas de valores mediante el uso de una consulta" utilizando declaraciones preparadas.
En caso afirmativo, ¿puedo saber cómo puedo implementarlo?
Inserción de valores múltiples con declaraciones preparadas PDO
Insertar múltiples valores en una declaración de ejecución. Porque según esta página es más rápido que las inserciones normales.
$data[] = ['valueA1', 'valueB1'];
$data[] = ['valueA2', 'valueB2'];
más valores de datos o probablemente tenga un bucle que complete los datos.
Básicamente, así es como queremos que se vea la declaración de inserción:
insert into table (fielda, fieldb, ... ) values (?,?...), (?,?...)....
Entonces, con las inserciones preparadas, necesita saber la cantidad de campos para crear una sola parte de VALORES y la cantidad de filas para saber cuántas veces repetirla.
Ahora, el código:
// create the ?,? sequence for a single row
$values = str_repeat('?,', count($data[0]) - 1) . '?';
// construct the entire query
$sql = "INSERT INTO table (columnA, columnB) VALUES " .
// repeat the (?,?) sequence for each row
str_repeat("($values),", count($data) - 1) . "($values)";
$stmt = $pdo->prepare ($sql);
// execute with all values from $data
$stmt->execute(array_merge(...$data));
Tenga en cuenta que este enfoque es 100 % seguro, ya que la consulta se construye enteramente a partir de partes constantes escritas explícitamente en el código, especialmente los nombres de las columnas.
Misma respuesta que el Sr. Balagtas, un poco más clara...
Las versiones recientes de MySQL y PHP PDO admiten declaraciones de varias filas INSERT
.
Descripción general de SQL
El SQL se verá así, suponiendo que le gustaría INSERT
tener una tabla de 3 columnas.
INSERT INTO tbl_name
(colA, colB, colC)
VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?) [,...]
ON DUPLICATE KEY UPDATE
funciona como se esperaba incluso con un INSERT de varias filas; agregue esto:
ON DUPLICATE KEY UPDATE colA = VALUES(colA), colB = VALUES(colB), colC = VALUES(colC)
Descripción general de PHP
Su código PHP seguirá las llamadas habituales $pdo->prepare($qry)
y $stmt->execute($params)
PDO.
$params
Será una matriz unidimensional de todos los valores para pasar al INSERT
.
En el ejemplo anterior, debería contener 9 elementos; PDO utilizará cada conjunto de 3 como una sola fila de valores. (Insertando 3 filas de 3 columnas cada una = matriz de 9 elementos).
Implementación
El siguiente código está escrito para mayor claridad, no para eficiencia. Trabaje con las array_*()
funciones de PHP para obtener mejores formas de mapear o recorrer sus datos si lo desea. Dado que se ejecuta una única consulta y cada consulta es una transacción en sí misma, no se requiere ninguna transacción explícita.
Asumiendo:
$dataVals
- matriz multidimensional, donde cada elemento es una matriz 1-d de una fila de valores para INSERTAR
Código de muestra
// setup data values for PDO. No memory overhead thanks to copy-on-write
$dataToInsert = array();
foreach ($dataVals as $row) {
foreach($row as $val) {
$dataToInsert[] = $val;
}
}
$onDup = "ON DUPLICATE KEY UPDATE colA=VALUES(colA)"; // optional
// setup the placeholders - a fancy way to make the long "(?, ?, ?)..." string
$rowPlaces = '(' . implode(', ', array_fill(0, count($colNames), '?')) . ')';
$allPlaces = implode(', ', array_fill(0, count($dataVals), $rowPlaces));
$sql = "INSERT INTO `tblName` (`colA`, `colB, colC)" .
" VALUES $allPlaces ON DUPLICATE KEY UPDATE $onDup";
// and then the PHP PDO boilerplate
$stmt = $pdo->prepare ($sql);
$stmt->execute($dataToInsert);