Как безопасно добавить необнуляемые столбцы в существующую таблицу в миграции Laravel? - PullRequest
0 голосов
/ 13 сентября 2018

Я хотел бы добавить необнуляемый столбец в существующую таблицу с несколькими строками в миграции Laravel.Я понимаю, что в SQL такое действие должно выполняться внутри транзакции в порядке

  1. , добавляя столбец
  2. , инициализируя столбец
  3. , делая его необнуляемым

, чтобы гарантировать

  • инициализацию, выполняемую без нарушения целостности БД, и
  • ALTER TABLE, чтобы не нарушать NOT NULLограничение,

Ниже приведен пример кода PostgreSQL (при условии, что users таблица содержит столбец old_col), ссылаясь на ответ :

BEGIN TRANSACTION;
  ALTER TABLE users ADD COLUMN new_col integer;
  UPDATE users SET new_col = old_col + 1;
  ALTER TABLE users ALTER COLUMN new_col SET NOT NULL;
COMMIT;

Обычный файл миграции Laravel, подобный этому, не будет работать.

public function up()
{
    Schema::table('users', function($table) {
        $table->integer('new_col');  // ->nullable(false) // later?
    });
}

Как реализовать транзакцию SQL или ее эквивалент в миграции Laravel?

ПРИМЕЧАНИЕ (отредактировано) :
Если вы хотите установить значение по умолчанию, и , если вам не нужно (абсолютно одновременно) обновлять столбец для существующих строк как функцию некоторых значений каждой строки,тогда вы можете просто указать ->default(0) или что-то вродев файле миграции (и избегайте всех хитростей!).Я не хотел устанавливать значение по умолчанию для добавляемого столбца.

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

Решение с тремя запросами:

DB::transaction(function () {
    Schema::table('users', function (Blueprint $table) {
        $table->integer('id_cloned')->nullable();
    });

    App\Models\User::query()->update([
        'id_cloned' => DB::raw('id + 1'),
        'updated_at' => DB::raw('now()') // if you want to touch the timestamp
    ]);

    Schema::table('users', function (Blueprint $table) {
        $table->integer('id_cloned')->nullable(false)->change();
    });
});

Альтернативное решение без DB :: raw parts, но генерирует отдельный запрос на обновление для каждой записи:

DB::transaction(function () {
    Schema::table('users', function (Blueprint $table) {
        $table->integer('id_cloned')->nullable();
    });

    foreach (App\Models\User::all() as $row) {
        $row->id_cloned = $row->id + 1;
        $row->save();
    }

    Schema::table('users', function (Blueprint $table) {
        $table->integer('id_cloned')->nullable(false)->change();
    });
});
0 голосов
/ 18 сентября 2018

вы можете использовать свой код в foreach как $ methodName = 'item-> get'. $ Method. '()';

Классовый предмет {

getFoo (); ...

GetBar (); ...

}

$ Methods = ['Foo', 'Bar'];

foreach ($ method как $ method) {

$ methodName = 'item-> get'. $ Method. '()';

echo $ methodName;

}

0 голосов
/ 14 сентября 2018

Вам нужно установить default value на то, что вы хотите:

public function up()
{
    Schema::table('users', function($table) {
        $table->integer('new_col')->default(0); 
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...