如何在 Laravel 5.1 迁移中使用外键

11

我需要在我的数据库中使用外键,但是在命令行中运行迁移命令后,我无法这样做,我得到了以下错误:

[Illuminate\Database\QueryException] SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL:alter table samples add constraint s amples_supplier_id_foreign foreign key (supplier_id) references suppliers (id))

[PDOException] SQLSTATE[HY000]: General error: 1215 无法添加外键约束

Samples 迁移:

Schema::create('samples', function (Blueprint $table) {
            $table->Increments('id',true);
            $table->string('variety',50);
            $table->integer('supplier_id')->unsigned();
            $table->foreign('supplier_id')->references('id')->on('suppliers');
            $table->string('lot_number');
            $table->date('date');
            $table->integer('amount');
            $table->integer('unit_id')->unsigned();
            $table->foreign('unit_id')->references('id')->on('unit');
            $table->string('technical_fact');
            $table->string('comments');
            $table->string('file_address');
            $table->integer('category_id')->unsigned();
            $table->foreign('category_id')->references('id')->on('category');
            $table->timestamps();
        });

供应商迁移:

Schema::create('suppliers', function (Blueprint $table) {
            $table->Increments('id',true);
            $table->string('supplier',50);
            $table->timestamps();
        });

我尝试使用新的 migration 进行样例操作,但是不成功:

Schema::create('samples', function (Blueprint $table) {
                $table->Increments('id',true);
                $table->string('variety',50);
                $table->integer('supplier_id')->unsigned();
                $table->string('lot_number');
                $table->date('date');
                $table->integer('amount');
                $table->integer('unit_id')->unsigned();
                $table->string('technical_fact');
                $table->string('comments');
                $table->string('file_address');
                $table->integer('category_id')->unsigned();
                $table->timestamps();
        });

        Schema::table('samples', function($table) {
            $table->foreign('supplier_id')->references('id')->on('suppliers');
            $table->foreign('unit_id')->references('id')->on('unit');
            $table->foreign('category_id')->references('id')->on('category');
        });

我试图将主键的长度固定为10,但再次失败了。

6个回答

8

顺序很重要。

在尝试引用表中的列作为约束之前,您需要确保您的“suppliers”表存在。

因此,如果您想在创建表时设置外键约束,请确保首先创建“suppliers”迁移,然后再创建“samples”迁移:

php artisan make:migration create_suppliers_table --create=suppliers
php artisan make:migration create_samples_table --create=samples

在迁移文件中添加模式代码,然后:

php artisan migrate

如果您不想担心表格创建的顺序,那么请先进行create_table迁移,但不要包含外键约束条件,接着再进行额外的迁移以添加您的外键。

php artisan make:migration create_samples_table --create=samples
php artisan make:migration create_suppliers_table --create=suppliers
php artisan make:migration alter_samples_table --table=samples   <-- add your foreign key constraints to this migration file

...在您的迁移文件中添加模式代码。然后使用以下命令进行迁移:

php artisan migrate

5

最后为该表生成迁移,记住它们应该是有序的,如果您遇到任何困难,请仅命名您的表_外键。

 Schema::table('samples', function($table) {
            $table->foreign('supplier_id')->references('id')->on('suppliers');
            $table->foreign('unit_id')->references('id')->on('unit');
            $table->foreign('category_id')->references('id')->on('category');
        });

将所有相关的外键放在最后并运行


2

试着用这种方式

Schema::table('samples', function($table) {
        $table->integer('supplier_id')->unsigned();
        $table->foreign('supplier_id')->references('id')->on('suppliers');
        $table->integer('unit_id')->unsigned();
        $table->foreign('unit_id')->references('id')->on('unit');
        $table->integer('category_id')->unsigned();
        $table->foreign('category_id')->references('id')->on('category');
    });

我说要这样做,但没有成功。 - Abolfazl Yavari
1
首先执行供应商迁移,然后执行样本迁移。因为如果没有供应商迁移,supplier_id 将无法作为外键工作。 - Imtiaz Pabel

1
KorreyD说的是对的!但是我创建了迁移,然后将迁移重命名以重新排序它们,这很简单: 重命名之前: 供应商迁移:2015_08_21_104217_supllier_table.php 样本迁移:2015_08_22_102325_samples_table.php 重命名之后: 样本迁移:2015_08_21_102325_samples_table.php 供应商迁移:2015_08_22_104217_supllier_table.php 我的问题解决了!因为供应商迁移在样本迁移之前运行。
注释:我试图使用反射器来更改任何使用迁移名称的地方。

我也一直在努力解决这些问题。看看laravelsd.com吧,你可以在那里创建数据库结构,然后将其全部导出。它会创建迁移并将所有关键绑定放在最后一个文件中。 - Tim van Uum
太好了!是的,那也可以。我没有提到这种方法,因为我不是 Laravel 专家,也不确定重命名迁移文件可能会出现什么问题。 - KorreyD

0
Schema::table('posts', function (Blueprint $table) {
    $table->unsignedInteger('user_id');

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

2
虽然这段代码可能回答了问题,但提供有关它如何以及/或为什么解决问题的附加上下文将改善答案的长期价值。 - Nic3500

0

大家都是正确的,但最简单的方法是像往常一样创建您的迁移文件。例如,您将拥有2019_01_21_123456_create_table_one_table.php ...

我把它们全部重命名了。

2019_01_21_0010_create_table_one_table.php
2019_01_21_0020_create_table_two_table.php
2019_01_21_0030_create_table_three_table.php
2019_01_21_0040_create_table_four_table.php

现在,如果我需要在table_two之前和table_one之后添加迁移,我只需将其更改为:
2019_01_21_0015_create_table_five_table.php

现在迁移的顺序将会是

2019_01_21_0010_create_table_one_table.php
2019_01_21_0015_create_table_five_table.php
2019_01_21_0020_create_table_two_table.php
2019_01_21_0030_create_table_three_table.php
2019_01_21_0040_create_table_four_table.php

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接