如何在 Laravel 中插入具有多个不同列的多行
How to insert multiple rows with multiple different columns in Laravel
我刚刚尝试了以下命令并收到了意外结果。
DB::table('locations')->insert([
['code' => 'YC', 'name' => 'York Clifton'],
['code' => 'YK', 'name' => 'York'],
['postcode' => 'DR1', 'name' => 'Jason'],
['postcode' => 'DLR', 'name' => 'Beckton']
]);
以上将在 table 中插入数据,如下所示:
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 |
+-----+--------------+------+----------+ +----+--------------+------+----------+
位置 table 是使用以下代码段构建的:
$table->string('name', 100);
$table->string('code', 4)->nullable();
$table->string('postcode', 10)->nullable();
当然,我想要的结果是向数据库中插入四行;前两个将填充 code
和 name
字段,而后两个插入将填充 postcode
和 name
.
我查看了文档,上面写着:
The query builder also provides an insert method for inserting records into the database table. The insert method accepts an array of column names and values:
You may even insert several records into the table with a single call to insert by passing an array of arrays. Each array represents a row to be inserted into the table.
我不完全确定 Laravel 在幕后做了什么,但它似乎预先构建了插入语句然后插入数据,忽略了列名键。
为了避免这个问题,我只是将具有不同列名的插入语句分开。
这让我想到,如果所有记录都是多余的(第一个数组中的键除外),为什么还要为所有记录设置列键呢?为什么不为插入方法设置两个参数;一个带有列名数组,一个带有数据。
文档没有说数组键必须全部相同,所以如果我遗漏了什么,那么如果有人能提供一些关于为什么这不起作用的见解,我将不胜感激。
tl;博士
当使用不同的列名时,如何将多行插入 table?
查看 Laravel 的代码刚刚看到了这种行为的原因。显然 Laravel 将插入查询编译为批量插入,而不是为每个传递的数组单独插入查询。
在插入方法中你可以看到查询是如何生成的:
$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', '...')
但是,您可以通过一次调用插入所有条目,方法是提供位置 table:
中的所有列
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']
]);
我刚刚尝试了以下命令并收到了意外结果。
DB::table('locations')->insert([
['code' => 'YC', 'name' => 'York Clifton'],
['code' => 'YK', 'name' => 'York'],
['postcode' => 'DR1', 'name' => 'Jason'],
['postcode' => 'DLR', 'name' => 'Beckton']
]);
以上将在 table 中插入数据,如下所示:
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 |
+-----+--------------+------+----------+ +----+--------------+------+----------+
位置 table 是使用以下代码段构建的:
$table->string('name', 100);
$table->string('code', 4)->nullable();
$table->string('postcode', 10)->nullable();
当然,我想要的结果是向数据库中插入四行;前两个将填充 code
和 name
字段,而后两个插入将填充 postcode
和 name
.
我查看了文档,上面写着:
The query builder also provides an insert method for inserting records into the database table. The insert method accepts an array of column names and values:
You may even insert several records into the table with a single call to insert by passing an array of arrays. Each array represents a row to be inserted into the table.
我不完全确定 Laravel 在幕后做了什么,但它似乎预先构建了插入语句然后插入数据,忽略了列名键。
为了避免这个问题,我只是将具有不同列名的插入语句分开。
这让我想到,如果所有记录都是多余的(第一个数组中的键除外),为什么还要为所有记录设置列键呢?为什么不为插入方法设置两个参数;一个带有列名数组,一个带有数据。
文档没有说数组键必须全部相同,所以如果我遗漏了什么,那么如果有人能提供一些关于为什么这不起作用的见解,我将不胜感激。
tl;博士
当使用不同的列名时,如何将多行插入 table?
查看 Laravel 的代码刚刚看到了这种行为的原因。显然 Laravel 将插入查询编译为批量插入,而不是为每个传递的数组单独插入查询。
在插入方法中你可以看到查询是如何生成的:
$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', '...')
但是,您可以通过一次调用插入所有条目,方法是提供位置 table:
中的所有列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']
]);