【问题标题】:"General error: 1005 Can't create table" Using Laravel Schema Build and Foreign Keys“一般错误:1005 无法创建表”使用 Laravel 架构构建和外键
【发布时间】:2012-08-07 07:38:03
【问题描述】:

基本上,我和这个人有同样的问题,减去表前缀。因为我没有表前缀,所以他的修复不起作用。 http://forums.laravel.com/viewtopic.php?id=972

我正在尝试使用 Laravel 的 Schema Builder 构建一个表,如下所示:

Schema::create('lessons', function($table)
{
    $table->increments('id');
    $table->string('title')->nullable();
    $table->string('summary')->nullable();
    $table->timestamps();
});

Schema::create('tutorials', function($table)
{
    $table->increments('id');
    $table->integer('author');
    $table->integer('lesson');
    $table->string('title')->nullable();
    $table->string('summary')->nullable();
    $table->string('tagline')->nullable();
    $table->text('content')->nullable();
    $table->text('attachments')->nullable();
    $table->timestamps();
});

Schema::table('tutorials', function($table)
{
    $table->foreign('author')->references('id')->on('users');
    $table->foreign('lesson')->references('id')->on('lessons');
});

问题是,当我运行此代码时(在 /setup 路由中),我收到以下错误:

SQLSTATE[HY000]: General error: 1005 Can't create table 'tutorials.#sql-2cff_da' (errno: 150)

SQL: ALTER TABLE `tutorials` ADD CONSTRAINT tutorials_author_foreign FOREIGN KEY (`author`) REFERENCES `users` (`id`)

Bindings: array (
)

基于网络上的帖子和关于如何设置 Laravel 的 Eloquent 关系的有限文档,我不确定我做错了什么......

users 已经存在,并且它确实有一个id 字段,即auto_increment。我也在用正确的关系(belongs_tohas_many)设置我的模型,但据我所知,这不是问题——这是数据库设置。 DB InnoDB。

外键到底做错了什么?

【问题讨论】:

    标签: mysql foreign-keys laravel


    【解决方案1】:

    通过使用:

     $table->unsignedInteger('author');
    

    代替:

     $table->integer('author');
    

    问题会解决的。

    问题是整数生成一个 int(11) 变量,而您需要一个 int(10) 变量。 unsignedInteger 会为你做的。

    【讨论】:

      【解决方案2】:

      基本上,您会收到此错误,因为迁移命令创建表的顺序与您为表提供的 FK 引用不匹配。

      如果你想创建一个 FK,它应该引用用户表中的 id,那么用户表必须存在。

      在您的示例中,需要先创建作者表和课程表。

      所以,我通过按这样的顺序(一个一个)创建表来解决这个问题,我可以成功地将 FK 引用到现有表。这样 Php Artisan Migration 就无法决定顺序。

      另一种解决方案是,您可以简单地重命名迁移命令提供的表或时间戳。

      【讨论】:

        【解决方案3】:

        使用外键-s时,请确保您的外键是unsigned。这对我有用

        【讨论】:

          【解决方案4】:

          已经列出的答案摘要,加上我的:

          1. 外键一般需要InnoDb,所以设置你的默认引擎,或者明确指定

            $table->engine = 'InnoDB';
            
          2. 外键需要引用的表存在。在创建密钥之前,请确保在较早的迁移中创建了引用的表。确保在单独的迁移中创建密钥。

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

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

          【讨论】:

          • 第 4 步已修复,现在 Jeffrey 的生成器中为 increments()
          • 酷!那是什么时候改变的?有 Github 链接吗?
          • Check This,之前有一个提交修复了创建,这个拉取请求也修复了数据透视表。
          【解决方案5】:

          你必须在 Laravel 5.4 中给整数一个无符号标志,像这样:

          public function up()
          {
              Schema::create('posts', function (Blueprint $table) {
                  $table->increments('post_id');
                  $table->text('title');
                  $table->text('text');
                  $table->integer('employee_post_id_number')->unsigned();
                  $table->foreign('employee_post_id_number')->references 
                  ('employee_id_number')->on('employees');
                  $table->timestamps();
              });
          }
          

          【讨论】:

            【解决方案6】:

            我也遇到了同样的问题。我刚刚注意到Laravel Schema docs 最底部的以下注释:

            注意:外键中引用的字段很可能是自动递增的,因此会自动成为无符号整数。请确保使用 unsigned() 创建外键字段,因为两个字段必须是完全相同的类型,两个表上的引擎必须设置为 InnoDB,并且引用的表必须在具有外键的表之前创建.

            对我来说,只要我这样设置外键字段:

            $table->integer('author')->unsigned();
            

            我没问题。

            编辑:另外,请确保外表中的字段已经创建,否则这可能会失败并出现同样的错误。

            【讨论】:

            • 数据类型也是我的问题,两个表都是 InnoDB。 int() 类型不匹配引发了一般错误 1005,然后是 errno:150。当 table_a 上的两个 PK 都与 table_b 上的 FK 列类型完全匹配时,一切都很好。谢谢!
            • 对于我代码中的类似情况,我不得不添加->nullable();在->unsigned(); 之后,它工作得很好:)
            • @ArifulHaque 在这里使用 ->nullable() 破坏了外键的目的。只要 ->unsigned() 就足够了。
            • 就我而言,问题是我的外键上没有 ->unsigned()
            • 您必须始终使用->unsigned(),如果您的 onDelete 操作设置为“设置 null”->onDelete('set null'),请添加 ->nullable()
            【解决方案7】:

            这在 Yii Framework 1.x 迁移中也发生在我身上。原来是 与上面的 Laravel 解决方案类似,它可能是由一个

            • 表名拼写错误(或尚不存在)
            • 列名拼写错误(或尚不存在)
            • 在不同表中使用同一数据库中的重复外键名称

            【讨论】:

              【解决方案8】:

              这是我在 Laravel 5 中所做的:

              // CREATING TABLE
              Schema::create('your_table_name', function (Blueprint $table) {
                  $table->engine = 'InnoDB';
                  $table->increments('id'); // index field example sample
                  $table->string('field2'); // some varchar/string field sample
                  $table->integer('field3'); // some integer field sample
                  $table->integer('field_some_table_id')->unsigned; //for field that contains foreign key constraint
              });
              
              // FOREIGN KEY CONSTRAINT
              Schema::table('stock', function ($table) {
                  $table->foreign('field_some_table_id')->references('id')->on('some_table')->onDelete('cascade')->onUpdate('cascade');
              });
              

              这就是结论的全部内容,它对我有用。

              【讨论】:

                【解决方案9】:

                最简单的方法是禁用外键检查:

                DB::statement('set foreign_key_checks=0');
                
                Schema::table( ... );
                
                DB::statement('set foreign_key_checks=1');
                

                【讨论】:

                  【解决方案10】:

                  Laravel5、MySQL55、CentOS65

                  在我的情况下,错误与此相同。

                  错误:[Illuminate\Database\QueryException]
                  SQLSTATE[HY000]:一般错误:1005 无法创建表 'nabsh.#sql-5b0_e' (errno: 121) (SQL: alter table usermeta add 约束 usermeta_uid_foreign 外键 (uid) 参考 users (id) 删除级联)。

                  我在这个问题的已批准答案中找到了一个很好的提示: ERROR: Error 1005: Can't create table (errno: 121)

                  提示:如果您尝试添加名称已在其他地方使用过的约束,您将收到此消息。

                  在我的情况下,此错误意味着已尝试添加的约束已存在于某处(但我无法在任何地方看到它们)。

                  我复制了输出错误查询并在 sequel pro 中执行它,然后希望我再次看到相同的错误。正如提示所说,我将约束名称更改为其他名称,然后它没有任何错误影响,因此 laravel5 + MySQL55 + CentOS65 中的约束名称生成器存在问题。

                  解决方案:尝试通过在表模式的外部方法中发送第二个参数来重命名约束。

                  Schema::table('tutorials', function($table)
                  {
                      $table->foreign('author')->references('id')->on('users');
                      $table->foreign('lesson')->references('id')->on('lessons');
                  });
                  

                  到 ->

                  Schema::table('tutorials', function($table)
                  {
                      $table->foreign('author', 'fk_tutorials_author')->references('id')->on('users');
                      $table->foreign('lesson', 'fk_tutorials_lesson')->references('id')->on('lessons');
                  });
                  

                  我希望它有所帮助。它适用于我的情况

                  【讨论】:

                    【解决方案11】:

                    我也遇到过这个问题。

                    我找到的解决方案是,在另一个表可以引用它之前,需要创建包含正在使用的外部 id 的 id 的表。基本上,您正在创建一个表并告诉 MySQL 引用另一个表的主键,但该表还不存在。

                    在您的示例中,需要先创建作者表和课程表。

                    创建表的顺序取决于工匠和您创建迁移文件的顺序。

                    我的意见是清空所有表的数据库并更改迁移文件名中的时间戳(或删除它们并以正确的顺序重新创建它们),以便在创建教程表之前创建作者表和课程表.

                    【讨论】:

                      【解决方案12】:

                      我收到了同样的错误,因为我忘记在引用的表上将表类型设置为 InnoDB:

                      $table->engine = 'InnoDB';
                      

                      【讨论】:

                      • 这解决了我的错误。不幸的是,我的引用表已经创建,所以我必须在迁移中进行手动更新: DB::statement('ALTER TABLE my_table ENGINE = InnoDB');
                      【解决方案13】:

                      我不是 100% 确定这些是否是失败的原因,但有几个指针。如果您使用旧版本的 mySQL 作为数据库,则默认表实现是不支持外键限制的 myISAM。由于您的脚本在外键分配上失败,您最好在 Schema 的 create 方法中使用此语法明确声明您希望 INNODB 作为引擎。

                      Schema::create('lessons', function($table)
                      {
                          $table->engine = 'InnoDB';
                      
                          $table->increments('id');
                          $table->string('title')->nullable();
                          $table->string('summary')->nullable();
                          $table->timestamps();
                      });
                      

                      这有望缓解您遇到的问题。

                      此外,虽然您可以事后声明外键,但我会在初始架构中创建外键,因为我可以轻松检查以确保我拥有正确的数据库引擎集。

                      Schema::create('tutorials', function($table)
                      {
                          $table->engine = 'InnoDB';
                      
                          $table->increments('id');
                          $table->integer('author');
                          $table->integer('lesson');
                          $table->string('title')->nullable();
                          $table->string('summary')->nullable();
                          $table->string('tagline')->nullable();
                          $table->text('content')->nullable();
                          $table->text('attachments')->nullable();
                          $table->timestamps();
                      
                          $table->foreign('author')->references('id')->on('users');
                          $table->foreign('lesson')->references('id')->on('lessons');
                      });
                      

                      希望这有助于/解决您的问题。

                      【讨论】:

                      • 在改组一些东西之后,我仍然得到一些关于外键约束的奇怪错误。奇怪的是——它确实工作,尽管有错误。事实证明,我在上面发布的错误是user.id 字段是int(10) unsigned 的结果,而外键是int(11)。不过感谢您的建议:)
                      • 没有问题 :) 使用上述架构时是否还会出现错误?或者当您输入数据时?
                      • 就在我创建架构的时候。据我所知,插入数据非常有效。
                      • 嘿@AndrewM,非常感谢您的跟进。遇到了完全相同的问题。
                      猜你喜欢
                      • 2019-11-14
                      • 2021-09-20
                      • 2016-07-26
                      • 2021-03-20
                      • 2014-01-26
                      • 1970-01-01
                      • 2019-06-14
                      • 1970-01-01
                      • 2013-12-30
                      相关资源
                      最近更新 更多