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 支持插入多行。

但是,如果您只有两行或更多行,则可以使用循环。

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中有两种方法可以提高插入数据的效率:

  1. 使用包含多行的单个 INSERT 语句:

    插入 t (col1, col2, col3) 值 (1, 2, 3), (4, 5, 6), (7, 8, 9);

  2. 准备一个 INSERT 语句并多次执行:

    准备插入到 t (col1, col2, col3) 值 (?, ?, ?); 执行 1、2、3 执行 4、5、6 执行 7、8、9

但是,支持这些改进中的任何一个都会增加 Row 和 Rowset 类的复杂性。这是由于当前 Zend_Db_Table_Row 类在调用 save() 时区分需要插入或更新的行的内部方式。这种区别由 Row 对象封装,因此 Rowset 不知道各个行是新行还是现有行的修改副本。因此,为了让 Rowset 类提供使用更高效 SQL 的多行 save() 方法,脏数据的管理必须完全重构。更简单的解决方案是让 Rowset 遍历其行,对每一行调用 save()。这对于 OO 封装更好,尽管它无助于优化 SQL 以插入行集。

无论如何,当最需要高效的 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,您应该编写一个循环并一次插入一行,在插入每一行后检索生成的 id。

于 2009-05-03T12:34:35.977 回答
19

您可以通过该方法执行任何您想要的 SQL 语法——包括多行INSERT语句。Zend_Db_Adapter_Abstract::query()

但是Zend_Db_TableZend_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),'(?)'));

希望这可以帮助

问候, Riki Risnandar

于 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 回答