You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 11迁移报错:无法创建product_details表(外键约束错误)

Laravel 11迁移外键约束错误解决方法

问题描述

执行php artisan migrate时创建product_details表失败,报错:

2024_05_16_010921_create_product_details_table  45.49ms FAIL

Illuminate\Database\QueryException 

SQLSTATE[HY000]: General error: 1005 Can't create table `distrisalsas`.`product_details` 
(errno: 150 "Foreign key constraint is incorrectly formed") (Connection: mysql, SQL: 
alter table `product_details` add constraint `product_details_product_id_foreign` foreign 
key (`product_id`) references `products` (`id`) on delete set null on update cascade)      

at vendor\laravel\framework\src\Illuminate\Database\Connection.php:813
809▕                     $this->getName(), $query, $this->prepareBindings($bindings), $e
810▕                 );
811▕             }
812▕
➜ 813▕             throw new QueryException(     
814▕                 $this->getName(), $query, 
$this->prepareBindings($bindings), $e
815▕             );
816▕         }
817▕     }

1   vendor\laravel\framework\src\Illuminate\Database\Connection.php:571
PDOException::("SQLSTATE[HY000]: General error: 1005 Can't create table 
`distrisalsas`.`product_details` (errno: 150 "Foreign key constraint is incorrectly 
formed")")

2   vendor\laravel\framework\src\Illuminate\Database\Connection.php:571
PDOStatement::execute()

迁移代码

products表迁移

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('product');
            $table->string('description');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};

brands表迁移

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('brands', function (Blueprint $table) {
            $table->id();
            $table->string('brand');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('brands');
    }
};

references表迁移

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('references', function (Blueprint $table) {
            $table->id();
            $table->string('reference');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('references');
    }
};

product_details表迁移

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('product_details', function (Blueprint $table) {
            $table->id();            
            $table->foreignId('product_id')
            ->constrained()
            ->cascadeOnUpdate()
            ->nullOnDelete();
            $table->foreignId('brand_id')
            ->nullable()
            ->constrained()
            ->cascadeOnUpdate()
                ->nullOnDelete();
            $table->foreignId('reference_id')
                ->nullable()
                ->constrained()
                ->cascadeOnUpdate()
                ->nullOnDelete();       
            $table->decimal('price')
                ->nullable();
            $table->timestamps();
            });
    }


    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('product_details');
    }
};

解决方案

1. 修正product_id字段的可空属性

你给product_id设置了nullOnDelete(),但字段本身没有标记为nullable()。MySQL不允许将非空字段通过外键约束设置为null,因此需要给product_id添加nullable():

$table->foreignId('product_id')
    ->nullable()
    ->constrained()
    ->cascadeOnUpdate()
    ->nullOnDelete();

2. 确认迁移文件执行顺序

Laravel按迁移文件名的时间戳顺序执行迁移,必须保证products、brands、references的迁移文件时间戳早于product_details的。例如,如果product_details的文件名是2024_05_16_010921_create_product_details_table,那另外三个表的迁移文件名时间戳应该更小(比如2024_05_16_010910_create_products_table)。如果顺序颠倒,创建product_details时父表还未存在,会触发外键约束错误。

3. 清理无效表并重新迁移

如果之前迁移失败导致数据库中存在不完整的表,先执行回滚:

php artisan migrate:rollback

或者手动删除数据库中的product_details表(如果存在),然后重新执行迁移:

php artisan migrate

内容的提问来源于stack exchange,提问作者erik_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 02:35:04