“常规错误:1005无法创建表”使用Laravel架构构建和外键

时间:2012-08-10 01:23:27

标签: mysql foreign-keys laravel

基本上,我和这个人有同样的问题,减去表前缀。因为我没有表前缀,他的修复不起作用。 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。

我对外键究竟做错了什么?

12 个答案:

答案 0 :(得分:78)

我一直有同样的问题。我刚刚在Laravel Schema docs的最底部注意到以下注释:

  

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

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

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

我没有问题。

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

答案 1 :(得分:11)

我不是百分之百确定这些是失败的原因,而是几个指针。如果您使用较旧版本的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');
});

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

答案 2 :(得分:8)

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

  1. 外键通常需要InnoDb,因此请设置默认引擎,或明确指定

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

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

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

答案 3 :(得分:6)

我也遇到了这个问题。

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

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

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

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

答案 4 :(得分:4)

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

$table->engine = 'InnoDB';

答案 5 :(得分:3)

Laravel5,MySQL55,CentOS65

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

  

错误:[Illuminate \ Database \ QueryException]
  SQLSTATE [HY000]:常规错误:1005无法创建表   'nabsh。#sql-5b0_e'(错误号:121)(SQL:alter table usermeta add   约束usermeta_uid_foreign外键(uid)参考   关于删除级联的usersid)。

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

  

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

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

我复制了输出错误查询并在sequel pro中执行它,然后希望我再次看到相同的错误。正如小贴士所说,我将约束名称更改为其他内容然后它没有出现任何错误,因此laravel5 + MySQL55 + CentOS65中的约束名称构建器出现问题。

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

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');
});

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

答案 6 :(得分:1)

在Yii Framework 1.x迁移中也发生了这种情况。原来那个 类似于上面的Laravel解决方案,它可能是由

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

答案 7 :(得分:1)

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

答案 8 :(得分:0)

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

exports.config = {
    capabilities: {
        'browser' : 'ie',
        'browserName': '',
        'browser_version' : '11',
        'os' : 'Windows',
        'os_version' : '7',
        'browserstack.user': 'XXX',
        'browserstack.key': 'XXX',
        'version': 11,
        'nativeEvents': false,
        'unexpectedAlertBehaviour': 'accept',
        'ignoreProtectedModeSettings': true,
        'enablePersistentHover': true,
        'disable-popup-blocking': true
    }
};

答案 9 :(得分:0)

这是我在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');
});

这一切都是为了结论,它对我有用。

答案 10 :(得分:0)

你必须在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();
    });
}

答案 11 :(得分:0)

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

如果您要创建一个FK,该FK应该引用users表中的id,则users表必须存在。

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

因此,我通过按顺序创建表(一个接一个)解决了这个问题,在这里我可以成功地将FK引用到现有表。因此,Php Artisan Migration无法决定顺序。

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