【问题标题】:Using migrations to delete table with foreign key使用迁移删除带有外键的表
【发布时间】:2013-06-11 02:43:50
【问题描述】:

我正在尝试回滚我的迁移。

我的迁移文件使用这样的外键

$table->foreign('user_one')->references('id')->on('users');
$table->foreign('user_two')->references('id')->on('users');

我的 down() 函数是这样的

public function down()
{
    Schema::drop('pm_convo');
    Schema::drop('pm_convo_replys');
}

当我运行迁移命令时

php artisan migrate:refresh --seed --env=local

我收到以下错误

SQLSTATE[23000]: Integrity constraint violation: 1217 Cannot delete or update a parent row: a foreign key constraint fails (SQL: drop table `pm_convo`) 

我不确定如何解决这个问题。

编辑:

我试过了:$table->dropForeign('pm_convo_user_one_foreign');

但是我也遇到了错误

【问题讨论】:

  • 您是否有另一个表具有引用pm_convo 的外键?
  • 是的,我愿意.. 有一个名为 pm_convo_replys 的表具有 $table->foreign('c_id_fk')->references('id')->on('pm_convo');
  • 在这种情况下,将两个drop 调用转过来。
  • 你在开玩笑哈哈哈我已经搜索了好几个小时...谢谢!!!!

标签: laravel laravel-4


【解决方案1】:

我认为这是一个更好的方法:

public function down()
{
    DB::statement('SET FOREIGN_KEY_CHECKS = 0');
    Schema::dropIfExists('tableName');
    DB::statement('SET FOREIGN_KEY_CHECKS = 1');
}

【讨论】:

  • 如果您有很多外键要处理,这是一种更简单的方法,但它适用于所有类型的数据库吗?如果您的迁移不完全正确地不小心留下外键检查,那么在开发过程中是否不可能?就我个人而言,我觉得正确订购它们会更干净
  • 谢谢,这个解决方案解决了我的数据库种子截断问题。
  • 我认为在这里使用dropIfExists 是不明智的。原则上,我发现编写依赖于数据库当前状态的迁移会更好。如果数据库的状态与您在运行 down 函数时所期望的不同(例如该表不存在),那么您的 up 函数可能存在严重错误,您确实需要先解决这个问题。
  • 暂时关闭SET FOREIGN_KEY_CHECKS 感觉就像是一种黑客行为,但考虑到在迁移中对我的数据库进行了具有明确名称的外部约束......这是某些情况下的最佳答案。 +1
  • Schema::disableForeignKeyConstraints(); Schema::drop('table_child');Schema::drop('table_parent');Schema::enableForeignKeyConstraints();根据手册。对于 Laravel 5.2
【解决方案2】:

pm_convo_replys 有一个引用pm_convo 的外键,因此您不能先删除pm_convo,否则会违反pm_convo_replys 中的外键约束。

要删除两者,您需要先删除pm_convo_replys

public function down()
{
    Schema::drop('pm_convo_replys');
    Schema::drop('pm_convo');
}

【讨论】:

    【解决方案3】:

    我也遇到过这类问题。迁移文件顺序是这里的主要问题。最好的方法是一个一个地创建迁移文件。应首先创建主要实体。每次创建迁移文件时都应刷新迁移。 (php artisan migrate:refresh)

    根据@abkrim 和@Eric

    public function down()
    {
        Schema::disableForeignKeyConstraints();
        Schema::drop('tableName');
        Schema::enableForeignKeyConstraints();
    }
    

    或者更安全:

    protected function dropColumn($table, $column) {
        try {
            Schema::disableForeignKeyConstraints();
            Schema::table($table, function (Blueprint $tbl) use ($column) {
                $tbl->dropColumn($column);
            });
        } catch (Illuminate\Database\QueryException $e)
        {
            Schema::table($table, function (Blueprint $tbl) use ($column) {
                $tbl->dropConstrainedForeignId($column);
            });
        } finally {
            Schema::enableForeignKeyConstraints();
        }
    }
    
    public function down() {
        $this->dropColumn('users', 'foreign_column');
    }
    

    【讨论】:

    • DB::statement('SET FOREIGN_KEY_CHECKS = 0');更简洁的代码
    • 是否需要再次启用外键约束?如果我评论 enableForeignKeyConstraints();
    【解决方案4】:

    我认为这是最正确的做法:

    public function down()
    {
        Schema::table('[table]', function (Blueprint $table) {
            $table->dropForeign('[table]_[column]_foreign');
            $table->dropColumn('[column]');
        });
    }
    

    【讨论】:

    • 我完全同意你的看法:这是正确的步骤顺序。这应该是公认的答案。
    • 这会触发ON DELETE吗?
    【解决方案5】:

    更喜欢这样做

        Schema::dropIfExists('tableNameChild');
        Schema::drop('tableNameParents');
    

    【讨论】:

      【解决方案6】:

      重要,这是针对 Laravel 5.4

      根据docs

      要删除外键,您可以使用 dropForeign 方法。外键约束使用与索引相同的命名约定。因此,我们将连接表名和约束中的列,然后在名称后面加上 "_foreign"

      $table->dropForeign('posts_user_id_foreign');
      

      或者,您可以传递一个数组值,该值会在删除时自动使用常规约束名称:

      $table->dropForeign(['user_id']);
      

      因为简单,我个人更喜欢第二种

      【讨论】:

        【解决方案7】:

        如果您在创建表时在foeign key 上添加cascade,您可以非常轻松地做到这一点。如果你这样做了,那么你可以很容易地删除表,而不需要像 PostgreSQL 这样的东西。

        DB::statement("drop table if exists tableName cascade");
        

        您所要做的就是将 SQL 表的语句放入原始格式。

        【讨论】:

        • 应该是DB::statement("drop table if exists tableName cascade");
        • 谢谢。没注意。
        猜你喜欢
        • 2019-01-29
        • 2018-11-10
        • 1970-01-01
        • 1970-01-01
        • 2019-01-22
        • 2015-07-06
        • 2020-05-07
        • 2016-11-13
        • 2015-03-25
        相关资源
        最近更新 更多