Подтвердить что ты не робот

Как добавить несколько строк в Zend_Db?

У меня есть массив с информацией, которая выглядит примерно так:

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

И я хочу добавить обе записи в базу данных.

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

не добавляет обе записи. Что я делаю не так? Должен ли я использовать Zend_ Db_Table?

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

работает конечно

4b9b3361

Ответ 1

Я не думаю, что Zend_Db поддерживает вставку нескольких строк.

Но если у вас просто две строки или еще немного, вы можете просто использовать цикл.

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


Bill Karwin, бывший разработчик Zend Framework, написал это на Nabble некоторое время назад

Стыки - это в основном объект коллекции, поэтому я бы добавил методы к этому классу, чтобы добавить строки в набор. Поэтому вы должны это сделать:

// 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(); 

Нет смысла передавать целое число для createRowset(), чтобы создать N пустых строк. Вам просто нужно будет проходить через них, чтобы все равно заполнить их значениями. Таким образом, вы можете написать цикл для создания и заполнения отдельных строк данными приложения, а затем добавить их в коллекцию.

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

Имеет смысл разрешить передачу массива массивов createRowset(), поскольку это будет соответствовать использованию передачи кортежа createRow().

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

Это будет выполнять тот же цикл, что и предыдущий пример выше (за исключением сохранения в конце), создавая новый набор строк новых строк, готовый к сохранению() d.

В SQL есть два способа повысить эффективность вставки данных:

  • Используйте один оператор INSERT с несколькими строками:

    INSERT INTO t (col1, col2, col3) ЗНАЧЕНИЯ (1, 2, 3), (4, 5, 6), (7, 8, 9);

  • Подготовьте инструкцию INSERT и выполните ее несколько раз:

    ПОДГОТОВКА ВСТАВКИ В t (col1, col2, col3) ЗНАЧЕНИЯ (?,?,?); ВЫПОЛНИТЬ 1, 2, 3 ВЫПОЛНИТЬ 4, 5, 6 ВЫПОЛНИТЬ 7, 8, 9

Однако поддержка любого из этих улучшений добавила бы сложности в классы Row и Rowset. Это связано с тем, что текущий класс Zend_Db_Table_Row различает строку, которая должна быть INSERTED или UPDATEd, когда вы вызываете save(). Это различие инкапсулируется объектом Row, поэтому Rowset не знает, являются ли отдельные строки новыми строками или измененными копиями существующих строк. Поэтому для класса Rowset предлагается многострочный метод save(), который использует более эффективный SQL, управление грязными данными должно быть полностью реорганизовано. Более легкое решение состоит в том, что Rowset выполняет итерацию по своим строкам, вызывая save() для каждого из них. Это лучше для инкапсуляции OO, хотя это не помогает оптимизировать SQL для вставки набора строк.

В любом случае очень редко приходится загружать много строк данных в типичном веб-запросе, когда существует большая потребность в эффективном SQL. Разница в эффективности для небольшого количества строк мала, поэтому это было бы заметным улучшением, только если вы загружаете огромное количество строк. Если это так, вы не должны использовать INSERT в любом случае, вы должны использовать инструкцию MySQL LOAD DATA или эквивалентную функцию, если используете другую марку RDBMS. INSERT обычно не самый эффективный выбор для загрузки большого количества данных.

Что касается возврата автоматически сгенерированных ключей, я бы не стал беспокоиться. Обратите внимание: если вы используете простой SQL (например, в CLI mysql), и вы вставляете несколько строк в один оператор INSERT, вы можете получить только последнее генерируемое значение id, а не значения id для всех вставленных строк. Это поведение SQL; это верно для любого языка или любой структуры.

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

Если вам нужен идентификатор для каждой строки, вы должны написать цикл и вставить строки по одному, извлекая сгенерированный идентификатор после каждой вставленной строки.

Ответ 2

Вы можете выполнить любой синтаксис SQL, который вы хотите - в том числе многострочные INSERT - с помощью метода Zend_Db_Adapter_Abstract::query().

Но методы классов Zend_Db_Table и Zend_Db_Table_Rowset не имеют поддержки для вставки нескольких строк за один раз.

Ответ 3

чтобы вставить несколько строк, вы можете использовать Zend_Db

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

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

(от Билла Карвина)

в вашем случае мы можем изменить это на этот код:

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

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

для генерации этих "(?), (?)" динамически, если данные динамические, вы можете попробовать использовать этот фрагмент:

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

надеюсь, что это поможет

С уважением, Рики Риснандар

Ответ 4

вот мое решение:

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);
    }

Ответ 5

Если вы используете ZF2, тогда решение может быть таким:

$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);