如何在Laravel迁移中将不可为空的列安全地添加到现有表中?

问题描述 投票:1回答:3

我想在Laravel迁移中的一些现有表中添加一个不可为空的列。在SQL中,我理解这样的操作应该按照顺序在事务内部执行

  1. 添加一列
  2. 初始化列
  3. 使它不可空

以保证

  • 在不破坏数据库完整性的情况下执行初始化,以及
  • ALTER TABLE不违反NOT NULL约束,

以下是一个示例PostgreSQL代码(假设users表有一个列old_col),指的是an answer

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?
    });
}

如何在Laravel迁移中实现SQL事务或其等价物?

注意(已编辑): 如果你想设置默认值,并且你不需要(绝对同时)更新现有行的列作为每行的某些值的函数,那么你可以简单地指定->default(0)或类似的东西。迁移文件(并避免所有技巧!)。我的问题是没有设置要添加的列的默认值。

php sql laravel postgresql migration
3个回答
1
投票

有三个查询的解决方案:

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部件的替代解决方案,但会为每条记录生成单独的更新查询:

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
投票

你需要将default value设置为你想要的任何东西:

public function up()
{
    Schema::table('users', function($table) {
        $table->integer('new_col')->default(0); 
    });
}

0
投票

你可以使用$ methodName ='item-> get'。$ method。'()';

class Item {

的getFoo(); ...

getBar(); ...

}

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

foreach($ methods as $ method){

$ methodName ='item-> get'。$ method。'()';

echo $ methodName;

}

© www.soinside.com 2019 - 2024. All rights reserved.