22

私は多かれ少なかれこのように見える情報を持つ配列を持っています:

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

そして、両方のエントリをデータベースに追加したいと思います。

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

両方のエントリを追加しません。私は何が間違っているのですか?Zend_ Db_Tableを使用する必要がありますか?

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

もちろん動作します

4

6 に答える 6

33

Zend_Db が複数行の挿入をサポートしているとは思えません。

ただし、行が 2 つまたはそれ以上ある場合は、ループを使用できます。

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


Zend Framework の元開発者であるBill Karwinは、少し前に 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

これにより、上記の前の例と同じループが実行され (最後の save() を除く)、新しい行の新しい行セットが作成され、save()d の準備が整います。

SQL でデータ挿入の効率を向上させる方法は 2 つあります。

  1. 複数の行で単一の INSERT ステートメントを使用します。

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

  2. INSERT ステートメントを準備し、複数回実行します。

    PREPARE INSERT INTO t (col1, col2, col3) VALUES (?, ?, ?); 実行 1、2、3 実行 4、5、6 実行 7、8、9

ただし、これらの改善のいずれかをサポートすると、Row および Rowset クラスが複雑になります。これは、save() を呼び出したときに、現在の Zend_Db_Table_Row クラスが INSERT する必要がある行と UPDATE する必要がある行を区別する内部的な方法によるものです。この区別は Row オブジェクトによってカプセル化されるため、Rowset は個々の行が新しい行なのか既存の行の変更されたコピーなのかを認識しません。したがって、Rowset クラスがより効率的な SQL を使用する複数行の save() メソッドを提供するには、ダーティ データの管理を完全にリファクタリングする必要があります。より簡単な解決策は、Rowset が各行で save() を呼び出して、その行を反復処理することです。これは、行セットを挿入するために SQL を最適化するのには役立ちませんが、OO カプセル化には適しています。

いずれにせよ、効率的な SQL の必要性が最も高い場合、通常の Web 要求で多くの行のデータを一括読み込みすることはほとんどありません。行数が少ない場合の効率の違いは小さいため、膨大な数の行を一括読み込みする場合にのみ、顕著な改善が見られます。その場合、とにかく INSERT を使用するべきではなく、MySQL の LOAD DATA ステートメントを使用するか、別の RDBMS ブランドを使用する場合は同等の機能を使用する必要があります。INSERT は通常、大量のデータをロードするための最も効率的な選択肢ではありません。

自動生成されたキーを返すことについては、気にしません。プレーン SQL を (たとえば mysql CLI で) 使用し、単一の 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

各行の ID が必要な場合は、ループを記述して行を 1 つずつ挿入し、各行が挿入されるたびに生成された ID を取得する必要があります。

于 2009-05-03T12:34:35.977 に答える
19

INSERTメソッドを介して、必要な SQL 構文 (複数行ステートメントを含む) を実行できますZend_Db_Adapter_Abstract::query()

Zend_Db_Tableただし、およびクラスのメソッドは、Zend_Db_Table_Rowset一度に複数の行を挿入することをサポートしていません。

于 2009-05-03T23:47:48.633 に答える
13

複数の行を挿入するには、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),'(?)'));

お役に立てれば

よろしく、 リキ・リスナンダー

于 2011-04-19T11:27:42.427 に答える
3

ここに私の解決策があります:

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);
    }
于 2013-08-10T23:22:24.860 に答える
1

仕事です。

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

Zend フレームワークで複数の挿入クエリを作成する方法

于 2013-03-05T16:14:34.527 に答える
0

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);
于 2013-02-25T16:12:39.463 に答える