如何在Laravel中插入具有多个不同列的多行

时间:2018-06-26 12:08:26

标签: php mysql laravel laravel-5.6

我刚刚尝试了以下命令,但收到了不希望的结果。

DB::table('locations')->insert([
    ['code' => 'YC', 'name' => 'York Clifton'],
    ['code' => 'YK', 'name' => 'York'],

    ['postcode' => 'DR1',  'name' => 'Jason'],
    ['postcode' => 'DLR',  'name' => 'Beckton']
]);

上面将这样在表中插入数据:

                Expected                                         Actual
+-----+--------------+------+----------+        +----+--------------+------+----------+
| id  |     name     | code | postcode |        | id |     name     | code | postcode |
+-----+--------------+------+----------+        +----+--------------+------+----------+
|   1 | York Clifton | YC   | NULL     |        |  1 | York Clifton | YC   | NULL     |
|   2 | York         | YK   | NULL     |        |  2 | York         | YK   | NULL     |
|   3 | Jason        | NULL | DR1      |        |  3 | DR1          | Jaso | NULL     |
|   4 | Beckton      | NULL | DLR      |        |  4 | DLR          | Beck | NULL     |
+-----+--------------+------+----------+        +----+--------------+------+----------+

locations表是使用以下代码段构建的:

$table->string('name', 100);
$table->string('code', 4)->nullable();
$table->string('postcode', 10)->nullable();

自然,我想要的结果是在数据库中插入四行;前两个将填充codename字段,而后两个插入将填充postcodename

我看了看写着的文档:

  

查询构建器还提供用于将记录插入数据库表中的插入方法。 insert方法接受列名和值的数组

     

您甚至可以通过一次调用将几个记录插入到表中,以便通过插入数组来插入。每个数组代表要插入表中的一行。

我不完全确定Laravel在幕后正在做什么,但是似乎它会先构建insert语句,然后插入数据,而忽略列名键。
为避免该问题,我只是将插入语句分隔为不同的列名。
这使我想到,如果所有记录都是多余的(除了第一个数组中的键除外),为什么还要麻烦拥有所有记录的列键?为什么没有两个用于insert方法的参数;一个带有列名数组,另一个带有数据。


文档中没有说数组键必须全部相同,因此,如果我缺少某些内容,那么如果有人可以提供一些无法理解为什么不起作用的信息,我将不胜感激。

tl; dr

使用不同的列名时如何在表中插入多行?

1 个答案:

答案 0 :(得分:5)

查看Laravel的代码,就可以看到这种行为的原因。显然,Laravel将插入查询编译为批处理插入,而不是将每个传递的数组编译为单独的插入查询。

在insert方法中,您可以看到查询的生成方式:

$sql = $this->grammar->compileInsert($this, $values);

如果进一步使用compileInsert方法,您会注意到查询的列是根据仅传递的第一个数组生成的:

$columns = $this->columnize(array_keys(reset($values)));

// We need to build a list of parameter place-holders of values that are bound
// to the query. Each insert should have the exact same amount of parameter
// bindings so we will loop through the record and parameterize them all.
$parameters = [];

foreach ($values as $record) {
    $parameters[] = '('.$this->parameterize($record).')';
}

$parameters = implode(', ', $parameters);

return "insert into $table ($columns) values $parameters";

因此,基本上,您的插入调用将执行查询:

INSERT INTO `locations` (`code`, `name`) 
VALUES ('YC', 'York Clifton'), 
       ('YK', 'York'),
       ('DR1', '...')

但是,您可以通过提供一次位置表中的所有列来通过一次调用插入所有条目:

DB::table('locations')->insert([
    ['code' => 'YC', 'name' => 'York Clifton', 'postcode' => null],
    ['code' => 'YK', 'name' => 'York', 'postcode' => null],

    ['code' => null, 'name' => 'Jason', 'postcode' => 'DR1'],
    ['code' => null, 'name' => 'Beckton', 'postcode' => 'DLR']
]);