如何将带有外键的NOT NULLABLE列添加到已包含数据的现有表中?

时间:2017-07-04 07:50:31

标签: php mysql database laravel foreign-keys

此问题的一个示例:

  

想象一下你有一个表项目。该表项目已经完成   包含数据。现在您要将project_type_id列添加到   table,它不能为NULL并且具有project_types的外键   表。

     

数据库看到project_type_id不能为NULL,因此它会插入一个   所有现有行的列中为0。 0中不存在   project_types表,因此外键约束失败。这个   意味着您无法添加外键。

我考虑过添加第一个"默认"行到project_types表并将所有项目链接到该类型。这不是一个好的解决方案,因为用户必须从"默认"更改所有类型。到正确的类型。

您对此问题的解决方案是什么?

4 个答案:

答案 0 :(得分:1)

我认为解决此问题的最佳方法是:

  
      
  1. 创建新迁移,以便将 project_type_id 列添加到项目表:
  2.   
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);
  }
}
  
      
  1. 现在您必须手动或从管理面板为 project_type_id 设置正确的值。

  2.   
  3. 现在您的列已准备好设置为外键,因此请继续进行新迁移,将 project_type_id 设置为外键。

  4.   
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命令来处理额外的工作。

我过去探讨过的其他解决方案是在同一迁移文件中处理该更新,但这很复杂。数据库结构和数据,最重要的是,它假定数据库具有数据。使用这种方法,即使它不是完全自动化的,您也可以在结构和数据之间清楚地分开。