2009-05-03 6 views
21

que tienen una matriz con la información que se ve más o menos así:¿Cómo agrego más de una fila con Zend_Db?

$data[] = array('content'=>'asd'); 
$data[] = array('content'=>'asdf'); 

Y quiero añadir dos entradas en la base de datos.

$db->insert('table', $data); 

no agrega las dos entradas. ¿Qué estoy haciendo mal? ¿Tengo que usar Zend_ Db_Table?

$data = array('content'=>'asdf'); 
$db->insert('table', $data); 

obras de curso

+3

La solicitud de función multi-inserto en Zend 2.0 ([ZF2-475] (http://framework.zend.com/issues/browse/ZF2-475) se ha cerrado como wontfix. – Tgr

Respuesta

32

no creo Zend_Db admite la inserción de múltiples filas.

Pero si solo tiene dos filas o un poco más, puede usar un bucle.

foreach ($data as $row) 
{ 
    $db->insert('table', $row) 
} 


Bill Karwin, un ex desarrollador de Zend Framework, escribió this on Nabble some time ago:

conjuntos de filas son, básicamente, un objeto de colección, por lo que me gustaría añadir métodos a esa clase para permitir filas que se añaden al conjunto. Por lo que debe ser capaz de hacer esto:

// creates a rowset collection with zero rows 
$rowset = $table->createRowset(); 

// creates one row with unset values 
$row = $table->createRow(); 

// adds one row to the rowset 
$rowset->addRow($row); 

// iterates over the set of rows, calling save() on each row 
$rowset->save(); 

No tiene sentido para pasar un entero a createRowset() para crear N filas vacías. Simplemente tendrías que iterar a través de ellos para poblarlos con valores de todos modos. De modo que también podría escribir un bucle para crear y completar filas individuales con datos de la aplicación, y luego agregarlos a la colección.

$rowset = $table->createRowset(); 
foreach ($appData as $tuple) 
{ 
    $row = $table->createRow($tuple); 
    $rowset->addRow($row); 
} 
$rowset->save(); 

Tiene sentido para permitir una matriz de matrices que se pasa a createRowset(), ya que esto sería coherente con el uso de pasar una tupla para createRow().

$rowset = $table->createRowset($appData); // pass array of tuples 

Este sería realizar el mismo bucle que el ejemplo anterior de arriba (excepto para el Save() al final), la creación de un nuevo conjunto de filas de nuevas filas, listo para ser save() d.

Hay dos maneras en SQL para mejorar la eficiencia de datos de inserción:

  1. uso una sola instrucción INSERT con varias filas:

    INSERT INTO t (col1, col2, col3) VALORES (1, 2, 3), (4, 5, 6), (7, 8, 9);

  2. Preparar una instrucción INSERT y ejecutarlo varias veces:

    PREPARAR INSERT INTO t (col1, col2, col3) VALORES; (?,?,?) EXECUTE 1, 2, 3 EXECUTE 4, 5, 6 EXECUTE 7, 8, 9

Sin embargo, el apoyo a cualquiera de estas mejoras añadiría complejidad a las clases de fila y conjunto de filas. Esto se debe a la forma interna en que la clase Zend_Db_Table_Row actual diferencia entre una fila que debe INSERTAR o ACTUALIZAR cuando llama a guardar().Esta distinción está encapsulada por el objeto Fila, por lo que Rowset no sabe si las filas individuales son nuevas filas o copias modificadas de las filas existentes. Por lo tanto, para que la clase Rowset ofrezca un método save() de varias filas que utiliza SQL más eficiente, la gestión de datos sucios tendría que ser totalmente refactorizada. La solución más fácil es que el Rowset itere sobre sus filas, llamando a save() en cada uno. Esto es mejor para la encapsulación OO, aunque no ayuda a optimizar SQL para insertar un conjunto de filas.

En cualquier caso, es muy raro cargar a granel muchas filas de datos en una solicitud web típica, cuando existe la mayor necesidad de SQL eficiente. La diferencia en la eficiencia para un pequeño número de filas es pequeña, por lo que sería una mejora notable solo si está cargando a granel una gran cantidad de filas. Si ese es el caso, no debe utilizar INSERT de todos modos, debe utilizar la instrucción LOAD DATA de MySQL o una función equivalente si usa otra marca RDBMS. INSERT no suele ser la opción más eficiente para cargar muchos datos.

En cuanto a devolver las claves generadas automáticamente, no me molestaría. Tenga en cuenta que si utiliza SQL simple (en la CLI de MySQL por ejemplo) e inserta varias filas en una sola instrucción INSERT, solo puede obtener el último valor de identificación generado, no los valores de id para todas las filas insertadas. Este es el comportamiento de SQL; es cierto para cualquier idioma o marco.

INSERT INTO t (col1, col2, col3) VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9); 
SELECT LAST_INSERT_ID(); -- returns only the id for the third tuple 

Si necesita el identificador para cada fila, usted debe escribir un bucle e insertar las filas uno a la vez, recuperar el identificador generado después de cada fila insertada.

+0

Esto no es verdad: $ sql = "INSERT INTO beautiful (nombre, edad) VALUES ('Helen', 24), ('Katrina', 21)"; funciona (solo un ejemplo) – Thomaschaaf

+0

tienes razón. Todavía no creo que zf lo soporte y no hay ninguna sugerencia en ninguna parte del manual. pero no estoy seguro. – markus

+1

¡LOL! ¡Ojalá hubiera tenido la oportunidad de votar por eso! Bien hecho Tharkun, por encontrar y volver a publicar eso. –

18

Puede ejecutar cualquier sintaxis SQL que desee, incluidas las declaraciones de varias filas INSERT, a través del método Zend_Db_Adapter_Abstract::query().

Pero los métodos de las clases Zend_Db_Table y Zend_Db_Table_Rowset no tienen ningún soporte para insertar varias filas de una vez.

+3

corect. pero insertMultiple() será útil y mucho más fácil ... –

+0

@Elzo Valugi, no hay ningún método 'insertMultiple()' en el manual y en el marco – Green

+1

"is" está presente, "will" es un (posible/probable) futuro. tal vez debería usar "would". Solo para aclarar :) –

10

para insertar varias filas puede utilizar Zend_Db

$stmt = $table->getAdapter()->prepare('INSERT INTO tablename (col1, col2, col3) VALUES (?, ?, ?), (?, ?, ?)'); 

$stmt->execute(array($value1, $value2, $value3, $value4, $value5, $value6)); 

(de Bill Karwin)

en su caso podemos cambiar eso a este código:

$data[] = array('content'=>'asd'); 
$data[] = array('content'=>'asdf'); 

$stmt = $table->getAdapter()->prepare('INSERT INTO table (col1) VALUES (?), (?)'); 
$stmt->execute($data); 

para generar estas ' (?), (?) 'dinámicamente, en caso de que los datos sean dinámicos, puede intentar usar este fragmento:

$values = implode(',',array_fill(0,count($data),'(?)')); 

esperanza esto ayuda

cordiales, Riki Risnandar

+2

No creo que esto funcione? Tengo $ list = array(); $ list [] = array (': x' => 1, ': y' => 1); $ stmt = $ this-> table-> getAdapter() -> prepare ('INSERT INTO aquí (x, y) VALUES (: x,: y), (: x,: y)'); $ stmt-> execute ($ list); y dice: 'Número de parámetro inválido: el número de variables vinculadas no coincide con el número de tokens'. Si no uso una matriz de MD, entonces está bien ... No creo que se suponga que ejecutar una matriz MD? –

+0

esto no funciona, recibo el error de que hay demasiados marcadores de posición. Intentando insertar 50,000 filas. – Ray

1

Si utiliza ZF2 continuación, la solución podría ser así:

$insert = $this->getSql()->insert(); 
foreach ($values as $value) { 
    $relation = array(
     'column_one' => $value, 
     'column_two' => $value 
    ); 
    $insert->values($relation, Insert::VALUES_MERGE); 
} 

$insertRes = $this->executeInsert($insert); 
1

Es un trabajo.

$query = 'INSERT INTO ' . $db->quoteIdentifier('table') . ' (`col1`, `col2`) VALUES '; 
    $queryVals = array(); 
    foreach ($data as $row) { 
     foreach($row as &$col) { 
      $col = $db->quote($col); 
     } 
     $queryVals[] = '(' . implode(',', $row) . ')'; 
    } 
    $stmt = $db->query($query . implode(',', $queryVals)); 

how to build multiple insert query in zend framework

2

aquí está mi solución:

public function saveRows($array) { 
     $vAmount = count($array); 
     $values  = array(); 
     $columns = array(); 

     foreach ($array as $colval) { 
      foreach ($colval as $column=>$value) { 
       array_push($values,$value); 
       !in_array($column,$columns) ? array_push($columns,$column) : null; 
      } 
     } 

     $cAmount = count($columns); 
     $values  = array_chunk($values, $cAmount); 
     $iValues = ''; 
     $iColumns = implode("`, `", $columns); 

     for($i=0; $i<$vAmount;$i++) 
      $iValues.="('".implode("', '", $values[$i])."')".(($i+1)!=$vAmount ? ',' : null); 

     $data="INSERT INTO `".$this->_name."` (`".$iColumns."`) VALUES ".$iValues; 
     die($data); 
     $this->query($data); 
    } 
+1

Realmente debería escapar de sus parámetros de consulta. – Eric

Cuestiones relacionadas