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

Jus*_*rty 3 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']
]);
Run Code Online (Sandbox Code Playgroud)

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

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

    ['postcode' => 'DR1',  'name' => 'Jason'],
    ['postcode' => 'DLR',  'name' => 'Beckton']
]);
Run Code Online (Sandbox Code Playgroud)

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

$table->string('name', 100);
$table->string('code', 4)->nullable();
$table->string('postcode', 10)->nullable();
Run Code Online (Sandbox Code Playgroud)

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

我看过的文档说:

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

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

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


文档没有说数组键必须全部相同,所以如果我遗漏了某些东西,那么如果有人可以提供一些无法理解的信息,我将不胜感激。

tl; dr

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

Mat*_*hai 5

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

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

$sql = $this->grammar->compileInsert($this, $values);
Run Code Online (Sandbox Code Playgroud)

如果您在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";
Run Code Online (Sandbox Code Playgroud)

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

INSERT INTO `locations` (`code`, `name`) 
VALUES ('YC', 'York Clifton'), 
       ('YK', 'York'),
       ('DR1', '...')
Run Code Online (Sandbox Code Playgroud)

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

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']
]);
Run Code Online (Sandbox Code Playgroud)