我想在Laravel迁移中的一些现有表中添加一个不可为空的列。在SQL中,我理解这样的操作应该按照顺序在事务内部执行
以保证
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)
或类似的东西。迁移文件(并避免所有技巧!)。我的问题是没有设置要添加的列的默认值。
有三个查询的解决方案:
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();
});
});
你需要将default value
设置为你想要的任何东西:
public function up()
{
Schema::table('users', function($table) {
$table->integer('new_col')->default(0);
});
}
你可以使用$ methodName ='item-> get'。$ method。'()';
class Item {
的getFoo(); ...
getBar(); ...
}
$ methods = ['Foo','Bar'];
foreach($ methods as $ method){
$ methodName ='item-> get'。$ method。'()';
echo $ methodName;
}