Как вставить несколько строк с несколькими разными столбцами в Laravel - PullRequest
0 голосов
/ 26 июня 2018

Я только что попробовал следующую команду и получил нежелательные результаты.

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     |
+-----+--------------+------+----------+        +----+--------------+------+----------+

Таблица местоположений построена с использованием следующего фрагмента:

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

Естественно, мой желаемый результат - вставить четыре строки в базу данных; первые два заполнят поля code и name, тогда как вторые два вставки заполнят поля postcode и name.

Я посмотрел документацию, которая гласит:

Конструктор запросов также предоставляет метод вставки для вставки записей в таблицу базы данных. Метод вставки принимает массив имен и значений столбцов :

Вы можете даже вставить несколько записей в таблицу одним вызовом , чтобы вставить, передав массив массивов. Каждый массив представляет строку для вставки в таблицу.

Я не совсем уверен, что Laravel делает под капотом, но кажется, что он предварительно строит операторы вставки, а затем вставляет данные, игнорируя ключи имен столбцов.
Чтобы избежать проблемы, я просто разделил операторы вставки с разными именами столбцов.
Это заставляет меня задуматься, зачем беспокоиться о наличии ключей столбцов для всех записей, если они лишние (за исключением ключей в первом массиве)? Почему бы не иметь два параметра для метода вставки; один с массивом имен столбцов, а другой с данными.


В документации не говорится, что все ключи массива должны быть одинаковыми, поэтому, если я что-то упустил, я был бы признателен, если бы кто-нибудь смог дать представление о том, почему это не работает.

ТЛ; др

Как вставить несколько строк в таблицу при использовании разных имен столбцов?

1 Ответ

0 голосов
/ 26 июня 2018

Глядя на код 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', '...')

Однако вы можете вставить все записи одним вызовом, указав все столбцы в таблице расположений:

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']
]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...