PDO preparado Inserta varias filas en una sola consulta

Resuelto hoball asked hace 54 años • 25 respuestas

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?

hoball avatar Jan 01 '70 08:01 hoball
Aceptado

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.

Herbert Balagtas avatar Jan 20 '2010 02:01 Herbert Balagtas

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 INSERTtener una tabla de 3 columnas.

INSERT INTO tbl_name
            (colA, colB, colC)
     VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?) [,...]

ON DUPLICATE KEY UPDATEfunciona 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.

$paramsSerá 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);
jamesvl avatar Dec 30 '2010 01:12 jamesvl