Миграция 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

окровавленныйadd constraint cb_category_parent_id_foreign foreign key (parent_id) referencescb_category(id`) на каскаде del на ete на каскаде обновления) (Привязки: массив ())

[PDOException] SQLSTATE [HY000]: общая ошибка: 1005 Невозможно создать таблицу 'eklik2.# Sql-7d4_e' (номер ошибки: 150)

Любая идея?

10 ответов

Решение

Вы должны разбить это на два блока схемы, один создавая столбцы, другой добавляя FK. mysql не может делать оба одновременно.

Работают два запроса:

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

Я могу опоздать на вечеринку, но официальные документы утверждают, что внешний ключ, в случае целого числа, должен быть ->unsigned();

http://laravel.com/docs/4.2/schema

Примечание. При создании внешнего ключа, который ссылается на возрастающее целое число, не забывайте всегда делать столбец внешнего ключа без знака.

Также Artisan не подведет, если вы (как и я) ошиблись unsigned() и я потратил довольно много часов, пытаясь выяснить, почему ключ не был создан.

Итак, две вещи: 1. Всегда делайте столбец внешнего ключа без знака в случае увеличения целых чисел 2. Проверьте правильность написания unsigned()

Также поздний ответ, но, вероятно, более идиоматический способ для Laravel 8:

      use App\Models\CbCategory;

...

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

Обратите внимание: я угадал название класса CbCategoryздесь. Использование ссылки на класс из первых рук (вместо прежней строки имени таблицы) позволяет вашим средствам проверки статического кода улавливать будущие изменения имени класса.
Так же _id-суффикс в parent_id имя столбца важно.


Пусть следующие ресурсы утолят вашу жажду знаний:

          Schema::create('categories', function (Blueprint $table) {
        $table->id();
        $table->integer('parent_id')->unsigned();
        $table->foreign('parent_id')->on('categories')->references('id');
    });

я получил ту же ошибку, когда использовал этот код, после изменения «$table-> integer ('parent_id') -> unsigned ()» на «$table-> bigInteger ('parent_id');» моя проблема решена.

Суть здесь в том, чтобы убедиться, что тип внешнего ключа совпадает с типом первичного ключа.

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

Попробуй это

БОЛЬШОЙ

      Schema::create('categories', function (Blueprint $table){
$table->id();
$table->bigInteger('parent_id')->unsigned()->nullable();
$table->foreign('parent_id')->references('id')->on('categories')->onDelete('cascade')->onUpdate('restrict');

Я думаю, у вас есть другая таблица, которая ссылается на текущую таблицу, которую вы хотите создать. У меня была эта проблема, и я удалил эту таблицу, и моя проблема была решена

Начиная с Laravel 8+ вам не нужно разбиваться на два блока схемы. Вы можете использоватьforeignIdFor(CbCategory::class, 'cb_category_id')и он создаст столбец с именемcb_category_id

Бывший.

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

Любые дополнительные модификаторы столбца (например, nulleable) должны вызываться перед ограниченным методом.

Вы можете использовать второй параметр в foreignIdFor для имени ссылочного столбца (в случае, если это не «id») НЕ для имени, которое вы хотите, чтобы оно было , в вашем случае имя будет автоматически «cb_category_id»

Laravel 8

Laravel также предоставляет поддержку для создания ограничений внешнего ключа, которые используются для обеспечения ссылочной целостности на уровне базы данных. Например, давайте определим столбец user_id в таблице сообщений, который ссылается на столбец 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:

$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 поддерживает внешние ключи только при создании таблицы, а не при изменении таблиц.

Документы

Другие вопросы по тегам