Laravel迁移自我引用外键问题

时间:2013-08-25 09:10:52

标签: php mysql foreign-keys migration laravel

您好我在使用迁移架构构建器创建表时遇到问题。 使用自引用外键的表发生此问题。 以下是产生错误的代码:

        Schema::create('cb_category', function($table)
    {
        $table->integer('id')->primary()->unique()->unsigned();
        $table->integer('domain_id')->unsigned();
        $table->foreign('domain_id')->references('id')->on('cb_domain'); 
        $table->integer('parent_id')->nullable(); 
        $table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade'); 
        $table->string('name');
        $table->integer('level');
    });

这是错误:

  SQLSTATE[HY000]: General error: 1005 Can't create table 'eklik2.#sql-7d4_e' (errno: 150) (SQL: alter table `cb_cate
del上的

gory add constraint cb_category_parent_id_foreign foreign key ( parent_id ) references cb_category ( id`)   更新级联上的ete级联)(绑定:数组(   ))

[PDOException]   SQLSTATE [HY000]:常规错误:1005无法创建表'eklik2。#sql-7d4_e'(错误号:150)

有什么想法吗?

7 个答案:

答案 0 :(得分:8)

你必须把它分成两个Schema块,一个创建列,另一个添加FK。 mysql不能同时做到这两点。

答案 1 :(得分:4)

我可能为聚会太迟了,但官方文件声称外键,如果是整数,必须是->unsigned();

http://laravel.com/docs/4.2/schema#foreign-keys

  

注意:创建引用递增的外键时   整数,记得始终使外键列无符号。

另外,如果你(因为我)拼错unsigned()并且我花了几个小时试图弄清楚为什么没有创建密钥,Artisan不会失败。

所以有两件事: 1.在递增整数的情况下,始终使外键列无符号 2.检查unsigned()

的拼写

答案 2 :(得分:1)

Schema::create('cb_category', function (Blueprint $table) {
        $table->increments('id')->unsigned();
        $table->integer('domain_id')->unsigned();
        $table->foreign('domain_id')->references('id')->on('cb_domain');
        $table->integer('parent_id')->nullable();
        $table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
        $table->string('name');
        $table->integer('level');
    });

试试这个

答案 3 :(得分:1)

两个查询有效:

Schema::create('cb_category', function($table)
{
    $table->integer('id')->primary()->unique()->unsigned();
    $table->integer('parent_id')->nullable();  
});

Schema::table('cb_category', function (Blueprint $table) 
{
    $table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
});

答案 4 :(得分:0)

我认为您有另一个表,该表引用了您要创建的当前表。 我遇到了这个问题,删除了那个表,问题就解决了

答案 5 :(得分:0)

Laravel 8

Laravel还提供了对创建外键约束的支持,这些外键约束用于强制数据库级别的参照完整性。例如,让我们在 posts 表上定义一个 user_id 列,该列引用 users 表上的 id 列:

Schema::table('posts', function (Blueprint $table) {
    $table->unsignedBigInteger('user_id');

    $table->foreign('user_id')->references('id')->on('users');
});

由于此语法相当冗长,因此Laravel提供了其他的,更简短的方法,这些方法使用约定来提供更好的开发人员体验。上面的示例可以这样写:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained();
});

foreignId方法是unsignedBigInteger的别名,而受约束的方法将使用约定来确定所引用的表和列的名称。如果表名不符合约定,则可以通过将表名作为参数传递给constrained方法来指定表名:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained('users');
});

您还可以为约束的"on delete""on update"属性指定所需的操作:

$table->foreignId('user_id')
      ->constrained()
      ->onDelete('cascade');

必须在constrained之前调用其他column modifiers

$table->foreignId('user_id')
      ->nullable()
      ->constrained();

要删除外键,可以使用dropForeign方法,将要删除的外键约束作为参数传递。外键约束根据表名和约束中的列使用与索引相同的命名约定,后跟"_foreign"后缀:

$table->dropForeign('posts_user_id_foreign');

或者,您可以将包含保留有外键的列名的数组传递给dropForeign方法。数组将使用Laravel模式构建器使用的约束名称约定自动转换:

$table->dropForeign(['user_id']);

您可以使用以下方法在迁移过程中启用或禁用外键约束:

Schema::enableForeignKeyConstraints();

Schema::disableForeignKeyConstraints();

SQLite默认情况下禁用外键约束。使用SQLite时,请确保在数据库配置中启用外键支持,然后再尝试在迁移中创建外键支持。另外,SQLite仅在创建表时才支持外键,而在表被更改时则不支持。

Docs

答案 6 :(得分:0)

对于 Laravel 8 ,反应也较晚,但可能更习惯惯用

use App\Models\CbCategory;

...

Schema::create("cb_category", function(Blueprint $table)
{
    $table->id();
    $table->foreignIdFor(CbCategory::class, "parent_id")
        ->cascadeOnUpdate()
        ->cascadeOnDelete()
        ->nullable();
});

请注意:我猜这里是CbCategory的类名。直接使用类引用(而不是以前的表名称字符串)使您的静态代码检查器可以接管将来的类名称更改。
此外,_id列名称的parent_id后缀也很重要。


愿以下资源能使您渴望知识: