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

时间:2015-02-17 21:52:40

标签: php mysql database laravel laravel-5

这是尝试通过使用包含以下内容的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 ;

在转储的底部,这与此特定表格相关:

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

从几个stackoverflow问题123;我改变了我原来的代码,将Schema :: table中的外键从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                                         

之后我无法再次回滚或迁移,而不会出现有关DB中已有用户表的其他类型的错误,因此每次尝试上述代码的版本时,我都会放弃我的每次DB。

我确定在修复此问题之后,它会在所有其他表格中出现,这些表格相似或者有多个外键,所以希望无论如何都能解决这个问题。

5 个答案:

答案 0 :(得分:5)

您必须更改迁移顺序

|-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

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

我有同样的问题,我做了什么?

简单...在您的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');
});}

:)

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:0)

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