Laravel 5 与外键相关的迁移错误

Laravel 5 Migration Error Related to Foreign Key

这是通过使用包含以下内容的 SQL 转储移植旧项目来学习 Laravel(特别是 v5.x)的尝试:

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `locationid` int(11) NOT NULL,
  `username` varchar(45) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
  `email` varchar(200) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
  `firstname` varchar(100) NOT NULL,
  `lastname` varchar(100) NOT NULL,
  `password` varchar(255) NOT NULL,
  `active` bit(1) DEFAULT b'1',
  `token` varchar(100) DEFAULT NULL,
  `token_created` timestamp NULL DEFAULT NULL,
  `role` varchar(45) NOT NULL DEFAULT 'user',
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email_UNIQUE` (`email`),
  UNIQUE KEY `username_UNIQUE` (`username`),
  KEY `location_idx` (`locationid`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

在转储的底部有这个与这个特定的相关 table:

ALTER TABLE `user`
  ADD CONSTRAINT `location_userfk` FOREIGN KEY (`locationid`) REFERENCES `location` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;

来自几个 Whosebug 问题 1, 2, 3;我修改了我的原始代码,将外键从 Schema::create 拆分为 Schema::table,并将 unsigned() 添加到每个字段:

public function up()
{
    Schema::create('users', function(Blueprint $table)
    {
        $table->increments('id');
        $table->integer('locationid')->unsigned();
        // $table->foreign('locationid')->references('id')->on('location');
        $table->string('username', 60)->unique();
        $table->string('email', 200)->unique();
        $table->string('firstname', 100);
        $table->string('lastname', 100);
        $table->string('password', 255);
        $table->boolean('active')->default(TRUE);
        $table->string('role', 45)->default('user');
        // $table->string('token', 255)->nullable()->default(NULL);
        // $table->string('token_create')->nullable()->default(NULL);
        $table->rememberToken();
        $table->timestamps();
    });

    Schema::table('users', function(Blueprint $table) 
    {
        $table->foreign('locationid')->references('id')->on('location');
    });
}

但是我在使用新创建的空数据库时迁移时仍然出现错误:

exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint' in /home/vagrant/projects/communityfuturesbc/vendor/laravel/framework/src/Illuminate/Database/Connection.php:358
Stack trace:
#0 /home/vagrant/projects/communityfuturesbc/vendor/laravel/framework/src/Illuminate/Database/Connection.php(358): PDOStatement->execute(Array) etc...

Next exception 'Illuminate\Database\QueryException' with message 'SQLSTATE[HY000]: General err
or: 1215 Cannot add foreign key constraint (SQL: alter table `users` add constraint users_loca
tionid_foreign foreign key (`locationid`) references `location` (`id`))' in /home/vagrant/proj
ects/communityfuturesbc/vendor/laravel/framework/src/Illuminate/Database/Connection.php:614   
Stack trace:                                                                                  
#0 /home/vagrant/projects/communityfuturesbc/vendor/laravel/framework/src/Illuminate/Database/Connection.php(570): Illuminate\Database\Connection->runQueryCallback('alter table `us...', Ar
ray, Object(Closure))

根据 MySQL 表示:

Error: 1215 SQLSTATE: HY000 (ER_CANNOT_ADD_FOREIGN)
Message: Cannot add foreign key constraint                                         

之后,我无法回滚或再次迁移,而不会收到关于用户 table 已经存在于数据库中的另一种类型的错误,所以每次我尝试上述代码的一个版本时,我都每次都删除我的数据库。

我确定在修复此问题后,它会出现在所有其他 table 中,它们相似或具有多个外键,因此希望任何修复都适用于其余部分。

好吧,这里有点令人困惑的部分,首先创建一个 table('users') when up 方法 运行 然后分别更新 table('users') 通过在同一个 table 中添加外键。我认为它不能使用迁移同时执行添加和更新。 对于您的代码的解决方案是:

public function up()
{
    Schema::create('users', function(Blueprint $table)
    {
        //...
        $table->integer('locationid')->unsigned();
        $table->foreign('locationid')->references('id')->on('location');
        //...
    });
}

现在,您通过创建 table 来创建您的外语。所以如果不让我知道它应该可以工作。

该错误是由尝试引用不存在的列的迁移引起的。要防止此问题,请在执行外键创建之前创建引用列。

要创建具有依赖关系的 table 结构,您可以按正确的顺序创建迁移文件,或者将所有迁移放入一个大文件中,或者至少创建所有 table 没有外键和创建另一个文件,该文件最后执行密钥创建。请记住,只有在您想要重新编写现有数据结构或想要修复迁移顺序时才有必要这样做。否则使用 php artisan make:migration 命令。

您必须更改迁移顺序

|-database/
|--migrations/
|---2015_02_02_141725_create_users_table.php
|---2015_03_01_234626_create_locations_table.php

应该是:

|-database/
|--migrations/
|---2015_01_01_234626_create_locations_table.php
|---2015_02_02_141725_create_users_table.php

最后:

php artisan migrate

我遇到了同样的问题,我该怎么办?

简单...在您的 create_users 迁移文件中试试这个...

public function up()
{

Schema::create('location', function(Blueprint $table)
{
    $table->increments('id');
    ...other attributes... 
    $table->rememberToken();
    $table->timestamps();
});

Schema::create('users', function(Blueprint $table)
{
    $table->increments('id');
    $table->integer('locationid')->unsigned();
    $table->string('username', 60)->unique();
    $table->string('email', 200)->unique();
    $table->string('firstname', 100);
    $table->string('lastname', 100);
    $table->string('password', 255);
    $table->boolean('active')->default(TRUE);
    $table->string('role', 45)->default('user');
    // $table->string('token', 255)->nullable()->default(NULL);
    // $table->string('token_create')->nullable()->default(NULL);
    $table->rememberToken();
    $table->timestamps();
});

Schema::table('users', function(Blueprint $table) 
{
    $table->foreign('locationid')->references('id')->on('location');
});}

:)

首先确保您的位置 table 存在。引用不存在的 table 可能会导致您遇到错误。