【问题标题】:Laravel migration will not add foreign keyLaravel 迁移不会添加外键
【发布时间】:2014-03-31 10:00:30
【问题描述】:

我是迁移的新手,并试图创建 2 个表,其中一个引用了另一个 id 的外键,但我遇到了添加键错误的一般失败。有什么我想念的吗?

错误:

[PDOException] SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint

代码:

    Schema::create('app_groups', function($table) {
     $table->increments('id');
     $table->string('app_name');
     $table->unsignedInteger('app_group_id');
     $table->timestamps();
  });

  Schema::create('app_to_bucket', function($table) {
     $table->increments('id');
     $table->unsignedInteger('app_group_id');
     $table->unsignedInteger('bucket_id');
     $table->timestamps();
  });
  Schema::table('app_to_bucket', function($table) {
     $table->foreign('app_group_id')->references('app_group_id')->on('app_groups')->onDelete('cascade');
  });

【问题讨论】:

  • 建表时为什么不加外键?

标签: php laravel


【解决方案1】:

这肯定会奏效。 Eloquent 主键是长度为 10 且无符号的整数。这就是关系不起作用的原因。

Schema::create('app_groups', function($table) {
     $table->string('app_name');
     $table->integer('app_group_id')->length(10)->unsigned();
     $table->timestamps();
  });

  Schema::create('app_to_bucket', function($table) {
     $table->integer('app_group_id');
     $table->integer('bucket_id')->length(10)->unsigned();
     $table->timestamps();
  });
  Schema::table('app_to_bucket', function($table) {
     $table->foreign('app_group_id')->references('app_group_id')->on('app_groups')->onDelete('cascade');

【讨论】:

  • 完美运行,谢谢。看起来更仔细,文档说:“注意:创建引用递增整数的外键时,请记住始终使外键列无符号。” (参考:laravel.com/docs/schema
  • 只是好奇,整数的默认长度是多少?长度(10)部分是必要的吗?
  • MySQL 中整数的默认长度是 11,但在 Laravel 中是 10。我不知道为什么。也许是有原因的。它可以在没有长度的情况下工作(10)。但我只是在任何情况下都使用它。
  • 我在 google 上搜索了这个问题 5 个小时,终于找到了您的解决方案,为我节省了一天的时间,谢谢
【解决方案2】:

我已经解决了这个问题。

问题在于 Laravel 自动假定递增列作为主键。所以我需要指定我的app_group_id 是主键。

 Schema::create('app_groups', function($table) {
     $table->string('app_name');
     $table->integer('app_group_id');
     $table->primary('app_group_id');
     $table->timestamps();
  });

  Schema::create('app_to_bucket', function($table) {
     $table->integer('app_group_id');
     $table->integer('bucket_id');
      $table->primary('bucket_id');
     $table->timestamps();
  });
  Schema::table('app_to_bucket', function($table) {
     $table->foreign('app_group_id')->references('app_group_id')->on('app_groups')->onDelete('cascade');
  });

【讨论】:

    【解决方案3】:

    好的,在使用 Laravel 在 MySQL 数据库中创建/添加外键约束时,您可能会遇到几个问题。

    首先,您应该检查您分配的列和表的名称。

    其次,在创建约束时检查数据库引擎。 请参阅文档 https://dev.mysql.com/doc/refman/5.7/en/innodb-foreign-key-constraints.html 它应该是 InnoDB

    Schema::create('app_groups', function($table) {
         // setting up the storage engine
         $table->engine='InnoDB';
         $table->increments('id');
         $table->integer('group_id')->unsigned();
         $table->string('app_name');
         $table->timestamps();
      });
    
    Schema::create('app_to_bucket', function($table) {
         $table->engine='InnoDB';
         $table->increments('id');
         $table->integer('app_group_id')->unsigned();
         $table->integer('bucket_id')->unsigned();
         $table->timestamps();
         $table->foreign('app_group_id')
               ->references('group_id')
               ->on('app_groups')
               ->onDelete('cascade');
    })
    ;}
    

    第三(可选),将您的约束分配(外键、索引等)移动到单独迁移

    【讨论】:

    • 表被创建为 MyISAM,这就是问题所在。设置 InnoDB 可以解决问题。谢谢!!!
    【解决方案4】:

    外键和引用键应该有相同的长度和相同的类型。如果您设置了满足该条件的那些键,则不会弹出错误:)

    【讨论】:

      【解决方案5】:

      必须先创建表,再创建外键:

      Schema::create('app_to_bucket', function($table) {
          $table->increments('id');
          $table->integer('bucket_id')->unsigned();
          $table->integer('app_group_id')->unsigned();
          $table->timestamps();
      });
      
      Schema::table('app_to_bucket', function($table) {
          $table->foreign('app_group_id')->references('app_group_id')->on('app_groups')->onDelete('cascade');
      });
      

      【讨论】:

      • 我已经尝试过了,得到了同样的错误...更新了上面的代码
      • 只是不要创建列,它将由您的数据库服务器添加。已编辑。
      • 我尝试删除该行,但它会抛出一个错误,提示“app_group_id”在表中不存在
      • 这是哪个数据库?尝试在我上次编辑时使用 unsigned()。
      • 奇怪,应该可以。这是另一个公认的答案:stackoverflow.com/questions/20999161/….
      【解决方案6】:

      试试这个:

      Schema::create('app_groups', function($table) {
           $table->increments('id');
           $table->integer('group_id')->unsigned();
           $table->string('app_name');
           $table->timestamps();
        });
       Schema::create('app_to_bucket', function($table) {
           $table->increments('id');
           $table->integer('app_group_id')->unsigned();
           $table->integer('bucket_id')->unsigned();
           $table->timestamps();
           $table->foreign('app_group_id')->references('group_id')->on('app_groups')->onDelete('cascade');
        });
      

      【讨论】:

      • 啊我错了,这不起作用...我需要 app_group_id 能够重复它不能递增。可以是多个具有相同 app_group_id 的 app_names
      • 我将“group_id”添加到“app_groups”。我的应用上有几乎完全相同的代码,而且运行良好。
      • 我完全复制粘贴了它,但它不起作用。当我尝试引用递增的 id 而不是 group_id 时,它工作正常
      • 您可以尝试将代码包装在: DB::statement('SET FOREIGN_KEY_CHECKS = 0'); //此处代码 DB::statement('SET FOREIGN_KEY_CHECKS = 1');看看会发生什么
      猜你喜欢
      • 2016-02-11
      • 2020-03-13
      • 2020-01-23
      • 2015-03-14
      • 2019-02-09
      • 2019-10-19
      • 2019-03-24
      • 2017-03-27
      • 2018-04-01
      相关资源
      最近更新 更多