[英]How to add un-nullable columns safely to an existing table in Laravel migration?
I would like to add an un-nullable column to an existing table with some rows in Laravel migration.我想在 Laravel 迁移中有一些行的现有表中添加一个不可为空的列。 In SQL, I understand such an action should be performed inside a transaction in the order of
在 SQL 中,我理解这样的操作应该按照以下顺序在事务内执行
so as to guarantee以保证
ALTER TABLE
not to violate the NOT NULL
constraint, ALTER TABLE
不违反NOT NULL
约束, The following is an example PostgreSQL code (assuming users
table has a column old_col
), referring to an answer :以下是 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;
An ordinary Laravel migration file like this would not work.像这样的普通 Laravel 迁移文件是行不通的。
public function up()
{
Schema::table('users', function($table) {
$table->integer('new_col'); // ->nullable(false) // later?
});
}
How can one implement a SQL transaction or its equivalent in Laravel migration?如何在 Laravel 迁移中实现 SQL 事务或等效的事务?
NOTE (edited) :注意(已编辑) :
If you want to set up the default value, and if you do not need to (absolutely simultaneously) update the column for the existing rows as a function of some values of each row, then you can simply specify ->default(0)
or something like that in the migration file (and avoid all the tricks!).如果要设置默认值,并且不需要(绝对同时)将现有行的列更新为每行某些值的函数,则只需指定
->default(0)
或迁移文件中的类似内容(并避免所有技巧!)。 My intention of the question was not to set up the default for the column to add.我提出这个问题的目的不是为要添加的列设置默认值。
The solution with three queries:三个查询的解决方案:
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();
});
});
Alternative solution without DB::raw parts, but will generate separate update query for every record:没有 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();
});
});
You need to set default value
to whatever you want:您需要将
default value
设置为您想要的任何default value
:
public function up()
{
Schema::table('users', function($table) {
$table->integer('new_col')->default(0);
});
}
you can your code in foreach like $methodName = 'item->get'.$method.'()';您可以在 foreach 中编写代码,例如 $methodName = 'item->get'.$method.'()';
class Item {类项目{
getFoo();... getFoo();...
getBar();... getBar();...
} }
$methods = ['Foo','Bar']; $methods = ['Foo','Bar'];
foreach($methods as $method){ foreach($methods 作为 $method){
$methodName = 'item->get'.$method.'()'; $methodName = 'item->get'.$method.'()';
echo $methodName;回声 $methodName;
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.