此问题的一个示例:
想象一下你有一个表项目。该表项目已经完成 包含数据。现在您要将project_type_id列添加到 table,它不能为NULL并且具有project_types的外键 表。
数据库看到project_type_id不能为NULL,因此它会插入一个 所有现有行的列中为0。 0中不存在 project_types表,因此外键约束失败。这个 意味着您无法添加外键。
我考虑过添加第一个"默认"行到project_types表并将所有项目链接到该类型。这不是一个好的解决方案,因为用户必须从"默认"更改所有类型。到正确的类型。
您对此问题的解决方案是什么?
答案 0 :(得分:1)
我认为解决此问题的最佳方法是:
- 创建新迁移,以便将 project_type_id 列添加到项目表:
醇>
php artisan make:migration add_project_type_column_to_projects_table --table=projects
public function up()
{
Schema::table('projects', function (Blueprint $table) {
$table->integer("project_type_id")->unsigned();
});
}
public function down()
{
Schema::table('projects', function (Blueprint $table) {
$table->dropColumn("project_type_id");
});
}
它会在每列中添加0值作为默认值,但没有问题,因为它还不是外键。
2.定义Project和ProjectType模型之间的关系
//Your Project class
class Project extends Model
{
protected $fillable=["your columns..."];
public function type()
{
return $this->belongsTo(ProjectType::class);
}
}
//Your ProjectType class
class ProjectType extends Model
{
protected $fillable=["Your columns..."];
public function projects()
{
return $this->hasMany(Project::class);
}
}
现在您必须手动或从管理面板为 project_type_id 设置正确的值。
- 醇>
现在您的列已准备好设置为外键,因此请继续进行新迁移,将 project_type_id 设置为外键。
php artisan make:migration set_project_type_id_column_as_foreign_key --table=projects
public function up()
{
Schema::table('projects', function (Blueprint $table) {
$table->foreign("project_type_id")
->references("id")
->on("project_types")
->onDelete("cascade")//is up to you
->onUpdate("cascade");// is up to you
});
}
public function down()
{
Schema::table('projects', function (Blueprint $table) {
$table->dropForeign("projects_project_type_id_foreign"); //This one could be different
});
}
现在你的表有一个新的(NOT NULLABLE)外键,其值正确。
答案 1 :(得分:0)
您应该拥有DB中存在的有效外键,例如:1
然后创建一个新的迁移:
$table->integer('project_type_id')->unsigned()->default(1);
$table->foreignkey('project_type_id')->references('id')->on('project_types');
然后,用户必须手动更改其中的每一个或随机更改它们(随机有效ID)foreach
。
答案 2 :(得分:0)
我认为这里的一个解决方法是首先添加新列而不用外键引用。然后更新该列的值,然后添加外键约束。像这样:
ALTER TABLE projects ADD COLUMN project_type_id INT;
-- now update with correct values
ALTER TABLE projects ADD CONSTRAINT fk_pt_id FOREIGN KEY (project_type_id)
REFERENCES yourTable(parent_id);
答案 3 :(得分:0)
如果必须部署到其他环境,则可以向project_type_id添加默认值(如@Ahmad Mobaraki所建议)。当然,您必须在project_type表中具有该值。
然后,根据您的业务逻辑,创建一个Artisan命令,该命令将提取所有行,并将project_type_id更新为正确的值。
最后,在运行迁移后,运行该Artisan自定义命令。
此时,您拥有一个具有正确值的不可为空的外键。
我遇到了同样的问题(是的,我知道,2019年)并以这种方式解决了。在其他环境中部署后,只需运行更新脚本即可。
我用来创建Artisan命令,这些命令在自动部署后手动运行。在大多数情况下,自动部署就可以了,但是当有类似这样的任务时,我发现最好的解决方案是使用定制的Artisan命令来处理额外的工作。
我过去探讨过的其他解决方案是在同一迁移文件中处理该更新,但这很复杂。数据库结构和数据,最重要的是,它假定数据库具有数据。使用这种方法,即使它不是完全自动化的,您也可以在结构和数据之间清楚地分开。