Laravel 5.1 迁移和播种无法截断外键约束中引用的 table

Laravel 5.1 Migration and Seeding Cannot truncate a table referenced in a foreign key constraint

我正在尝试 运行 迁移(见下文)并为数据库播种,但是当我 运行

php artisan migrate --seed

我收到这个错误:

Migration table created successfully.
Migrated: 2015_06_17_100000_create_users_table
Migrated: 2015_06_17_200000_create_password_resets_table
Migrated: 2015_06_17_300000_create_vehicles_table

[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table
referenced in a foreign key constraint (`app`.`vehicles`, CONSTRAINT `vehic
les_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `app`.`users` (`id`
)) (SQL: truncate `users`)

[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table
referenced in a foreign key constraint (`app`.`vehicles`, CONSTRAINT `vehic
les_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `app`.`users` (`id`
))

我查看了这个错误的含义,还找到了 of other people running into the same problem, even just related to using MySQL 和他们的解决方案,但应用:

DB::statement('SET FOREIGN_KEY_CHECKS=0;'); and 
DB::statement('SET FOREIGN_KEY_CHECKS=1;'); 

在 down() 中似乎不起作用,当我 运行 在 MySQL 中描述时,table 看起来是正确的。

正确命名迁移以确保首先迁移用户 table,然后迁移车辆,以便可以应用外键,并且正确设置的 table 会建议迁移是 运行,但随后发生错误。我删除并重新创建了数据库并再次尝试,结果相同。我也不明白为什么它试图 t运行cate 在数据库的第一次迁移和种子上,我不会想到当你试图 运行 php artisan migrate:refresh --seed.

// 2015_06_17_100000_create_users_table.php

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('username', 60)->unique();
            $table->string('email', 200)->unique();
            $table->string('password', 255);
            $table->string('role')->default('user');
            $table->rememberToken();
            $table->timestamps();
        });
    }
}

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

// 2015_06_17_300000_create_vehicles_table.php

class CreateVehiclesTable extends Migration
{
    public function up()
    {
        Schema::create('vehicles', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->string('make');
            $table->string('model');
            $table->string('year');
            $table->string('color');
            $table->string('plate');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
        });
    }
}

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

如错误所述,您不能截断外键引用的表。删除应该有效...

DB::table('some_table')->delete();
DB::statement('SET FOREIGN_KEY_CHECKS=0;');
App\User::truncate();
DB::statement('SET FOREIGN_KEY_CHECKS=1;');

而且有效!

clear一个table使用Eloquent:

Model::query()->delete();

使用默认用户模型的示例

User::query()->delete();

这是每次都对我有用的方法。 添加外键时,请确保添加 cascade。 语法是这样的

$table->foreign('column')->references('id')->on('table_name')->onDelete('cascade');

确保将 id 替换为适用于您的任何字段。

现在在 运行 播种之前添加这个而不是 trucate

DB::statement('DELETE FROM table_name');

它将删除所有数据。 希望这有帮助。

你可以使用

DB::table('your_table_name')->delete();

清空table,这不会删除table结构。但是自增id不会从初始号开始。

您可以将其删除。

$table->dropForeign('posts_user_id_foreign');

下降前

Schema::disableForeignKeyConstraints();

和关闭前运行方法

Schema::enableForeignKeyConstraints();

我正在使用 Laravel 7.x,这对我有用。不用说,它应该只用于开发。要了解更多信息,请查看 here.

DatabaseSeeder.php

    <?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        // the Eloquent part and disabling and enabling of foreign keys is only intended for development
        Eloquent::unguard();

        //disable foreign key check for this connection before running seeders
        DB::statement('SET FOREIGN_KEY_CHECKS=0;');

        $this->call(RolesTableSeeder::class);
        $this->call(UsersTableSeeder::class);

        // supposed to only apply to a single connection and reset it's self
        // but I like to explicitly undo what I've done for clarity
        DB::statement('SET FOREIGN_KEY_CHECKS=1;');
    }
}

我在角色和权限设置方面遇到了同样的问题,这就是我所做的,并且效果如我所愿。 Truncate() 会将增量列重置为 1,但抛出外键错误,而另一方面 delete 工作正常但不会重置增量列,所以我在我的 Seeder 文件中执行了以下操作(即 RoleSeeder.php 在我的情况)

1. [ delete() 方法]

$roles = [];

... // Some foreach statement to prepare an array of data for DB insert()

// Delete and Reset Table
DB::table('roles')->delete();
DB::statement("ALTER TABLE `roles` AUTO_INCREMENT = 1");
// Insert into table
DB::table('roles')->insert($roles);

这将级联附加到 角色 table 的所有其他 child table。在我的例子中 users_roles table。这样我就避免了禁用和启用外键检查。

2。要记住的事情/第二种方法[ truncate() 方法]

如果您不打算删除存储在 child 的 table 中的所有数据(在我的例子中是 users_roles table).. . 您可以使用 truncate() 然后在 DatabaseSeeders.php 文件中禁用和启用外键检查。当我对此进行测试并且 users_roles 数据完好无损时,受影响角色的种子 table.

//RoleSeeders.php File

$roles = [];

... // Some foreach statement to prepare an array of data for DB insert()

// Truncate Table
DB::table('roles')->truncate();
// Insert into table
DB::table('roles')->insert($roles);

然后在 DatabaseSeeder.php 文件中,你做;

public function run()
{
    DB::statement('SET FOREIGN_KEY_CHECKS=0;');

    $this->call([
        RoleSeeder::class,
    ]);

    DB::statement('SET FOREIGN_KEY_CHECKS=1;');
}

但我更喜欢 delete() 方法,因为我不必 disable/enable 外键检查