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

Posted

技术标签:

【中文标题】Laravel 5 与外键相关的迁移错误【英文标题】:Laravel 5 Migration Error Related to Foreign Key 【发布时间】:2015-04-18 18:11:20 【问题描述】:

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

来自几个***问题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                                         

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

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

【问题讨论】:

location 表是否已经生成? 添加外键前需要创建位置表。 我自己列举了迁移文件。然后使用 artisan migrate 命令生成新的迁移。 @dschniepp 您如何定义要迁移的表的顺序?看起来您可能只能通过制作一个迁移文件并在一个文件中创建多个表,或者专门定制初始迁移来做到这一点,这对于其他开发人员来说更难模仿。希望能够安装、创建数据库、composer install、artisan migrate 和 artisan seed,以使其他开发人员启动并运行 我自己枚举文件2014_10_29_[1...100]_create...,然后通过artisan 命令创建任何进一步的迁移文件。 【参考方案1】:

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

【讨论】:

【参考方案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】:

您必须更改迁移顺序

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

【讨论】:

【参考方案4】:

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

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

【讨论】:

【参考方案5】:

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

public function up()

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

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

【讨论】:

以上是关于Laravel 5 与外键相关的迁移错误的主要内容,如果未能解决你的问题,请参考以下文章

无法添加外键约束 - Laravel 迁移错误

如何在 laravel 5.1 迁移中使用外键

Laravel 5.2 迁移:无法添加 char 数据类型的外键

Laravel 5.3 迁移:1215 无法添加外键约束

Laravel 迁移外键错误

Laravel-7 迁移中的外键约束形成错误