25

我刚刚创建了一个新的 Laravel 4 项目,并且发现架构构建器的外键方面发生了奇怪的事情。如果我->foreign()在任何迁移中使用该方法,我会抛出 MySQL 错误 150 和一般错误 1005。根据 laravel.com/docs 上的文档,底部的两个场景应该有效吗?有谁知道他们为什么不这样做?

以下确实有效:

    Schema::create('areas', function($table)
    {
        $table->engine ='InnoDB';
        $table->increments('id');

        $table->integer('region_id')->references('id')->on('regions');

        $table->string('name', 160);
        $table->timestamps();
    });

但是这两个不起作用:

    Schema::create('areas', function($table)
    {
        $table->engine ='InnoDB';
        $table->increments('id');

        $table->foreign('region_id')->references('id')->on('regions');

        $table->string('name', 160);
        $table->timestamps();
    });

    Schema::create('areas', function($table)
    {
        $table->engine ='InnoDB';
        $table->increments('id');

        $table->integer('region_id');
        $table->foreign('region_id')->references('id')->on('regions');

        $table->string('name', 160);
        $table->timestamps();
    });
4

5 回答 5

53

检查你的id类型。Laravel 4 创建一个带有 int(10) 无符号的增量 id。如果您创建一个基本整数并尝试在其上放置一个外键,它将失败。

正如此链接的文档中所建议的那样,您应该创建外部 id$table->unsignedInteger(YOUR_ID_NAME);以使其工作。

于 2013-06-05T08:21:01.823 回答
7

在这个问题上也有一些答案“一般错误:1005 无法创建表”使用 Laravel 模式构建和外键

那里列出的答案摘要,包括我的:

  1. 外键一般需要 InnoDb,所以设置你的默认引擎,或者明确指定 $table->engine = 'InnoDB'; 如果你的表已经创建并且默认为 MyISAM,你可能需要改变它。

  2. 外键要求被引用的表存在。在创建密钥之前,请确保在较早的迁移中创建了引用的表。考虑在单独的迁移中创建密钥以确保。

  3. 外键要求数据类型一致。检查引用的字段是否相同类型,是否有符号或无符号,长度是否相同(或更少)。

  4. 如果您在手动编码迁移和使用生成器之间切换,请确保检查您正在使用的 id 类型。Artisan 默认使用increments()但 Jeffrey Way 似乎更喜欢integer('id', true)

于 2013-09-20T13:31:49.377 回答
5

前一天有同样的问题。

问题的根源是:具有外键的列必须与该键的类型相同。你有不同的类型:INT/UNSIGNED INT

这使得 id 成为UNSIGNED INT

$table->increments('id');

这使得 region_id 成为INT

$table->integer('region_id')->references('id')->on('regions'); 

为了解决这个问题,也将 region_idUNSIGNED INT设为

$table->integer('region_id')->unsigned()->references('id')->on('regions'); 
                              ^^^^^^^^^ note here

Laravel 的文档中提到了这一点:

注意:创建引用递增整数的外键时,请记住始终使外键列无符号。

于 2014-03-23T13:29:57.180 回答
2

它有效,但有时您只需要小心并尝试了解幕后发生的事情。

正如我在评论中所说。当你第一次运行迁移而不创建相关列时,Laravel 迁移服务会创建你的表,然后,当你再次尝试迁移时,它总是会给你一个错误,说表已经存在。

因此,您只需再次drop table areas运行php artisan migrate即可修复所有问题。

编辑:

我刚刚在这里创建了您的迁移(如下)并且它有效。

正如你所看到的,我没有使用 MySQL,所以它一定是 MySQL 的问题。检查 MySQL 外键文档以查看您的元数据是否符合 InnoDB 要求:http ://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html 。

<?php

use Illuminate\Database\Migrations\Migration;

class CreateAreasTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('regions', function($table)
         {
             // $table->engine = 'InnoDB';
             $table->increments('id');
             $table->string('name', 160)->unique();
             $table->timestamps();
        });

        Schema::create('areas', function($table)
        {
            // $table->engine ='InnoDB';
            $table->increments('id');

            $table->integer('region_id');
            $table->foreign('region_id')->references('id')->on('regions');

            $table->string('name', 160);
            $table->timestamps();
        });     
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
    Schema::drop('areas');
    Schema::drop('regions');
    }

}

在此处输入图像描述

于 2013-06-04T22:58:30.830 回答
1

antonio carlos 是对的,请确保您首先创建了外键的引用表。

尝试首先迁移没有外键的表,然后再进行分配外键的迁移。在这种状态下,laravel 确定引用键是存在的。而且您不必在工匠错误期间删除表格。

于 2013-07-20T06:34:31.620 回答