Laravel 4迁移问题中的外键

Posted

技术标签:

【中文标题】Laravel 4迁移问题中的外键【英文标题】:Foreign keys in Laravel 4 migrations issue 【发布时间】:2013-05-31 11:49:42 【问题描述】:

我刚刚创建了一个新的 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();
    );

【问题讨论】:

Laravel 4 Migrations throwing 1072 error 的可能重复项 这个问题是关于为什么上面不起作用,另一个是关于MySQL 1072错误。 刚刚进入 Laravel 并且也成功了。我的解决方法是使用单独的迁移添加外键。它有效,但感觉有点不对。 【参考方案1】:

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

按照this link 文档中的建议,您应该使用$table->unsignedInteger(YOUR_ID_NAME); 创建外部ID 以使其工作。

【讨论】:

例如:(users 表)$table->increments('id'); 和(posts 表)$table->unsignedInteger('user_id'); \n $table->foreign('user_id')->references('id')->on('users'); 我使用了正确的类型,就像$table->integer('user_id')->unsigned(); 并且在数据库中设置了 unsigned 属性,但它对我不起作用。我更新了我的代码以使用unsignedInteger,现在一切正常 我自己也遇到过同样的问题 - Dayle Rees 已经很好地解释了它(带有示例)daylerees.com/codebright/eloquent-relationships @alairock 很好的例子,因为我犯的一个菜鸟错误是试图在列存在之前创建外键。首先声明该列,然后将其设为外键。为此 +1!【参考方案2】:

还有一些关于这个问题的答案"General error: 1005 Can't create table" Using Laravel Schema Build and Foreign Keys

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

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

    外键需要引用的表存在。在创建密钥之前,请确保在较早的迁移中创建了引用的表。确保在单独的迁移中创建密钥。

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

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

【讨论】:

我的问题是它是一个以前创建的表并且默认为 MyISAM。更新被引用到 InnoDB 的表后,一切都很好。【参考方案3】:

前一天有同样的问题。

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

这使得 id 成为 UNSIGNED INT

$table->increments('id');

这使得 region_id 成为 INT

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

要解决这个问题,请将 region_id 设置为 UNSIGNED INT

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

Laravel 的文档有 mention 关于这个:

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

【讨论】:

【参考方案4】:

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

正如我在评论中所说。当你第一次运行迁移而不创建相关列时,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');
    


【讨论】:

那行不通。我删除了数据库,创建了一个新数据库,运行php artisan migration:install,然后运行php artisan migrate,错误仍然存​​在,但前提是我提及-&gt;foreign()【参考方案5】:

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

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

【讨论】:

以上是关于Laravel 4迁移问题中的外键的主要内容,如果未能解决你的问题,请参考以下文章

如何修复laravel迁移中的外键错误

:完整性约束违规:1452 无法添加或更新子行:laravel 迁移中的外键约束失败

将相同的外键添加到 4 行 Laravel

Laravel 5.2 迁移:无法添加 char 数据类型的外键

Laravel 5.3,MySQL,迁移中正确的外键设置(一对多,多对多)

SQLSTATE [HY000] Laravel 8 中的外键约束格式错误