Миграция: невозможно добавить ограничение внешнего ключа

207

Я пытаюсь создать внешние ключи в Laravel, однако при переносе таблицы с помощью artisan я следующую ошибку:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `priorities` add constraint priorities_user_id_foreign foreign 
key (`user_id`) references `users` (`id`))     

Мой код миграции таков:

файл миграции приоритетов

public function up()
{
    //
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}

файл миграции пользователей

public function up()
{
    //
    Schema::table('users', function($table)
    {
    $table->create();
    $table->increments('id');
    $table->string('email');
    $table->string('first_name');
    $table->string('password');
    $table->string('email_code');
    $table->string('time_created');
    $table->string('ip');
    $table->string('confirmed');
    $table->string('user_role');
    $table->string('salt');
    $table->string('last_login');

    $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
        Schemea::drop('users');
}

Любые идеи относительно того, что я сделал неправильно, я хочу получить это прямо сейчас, так как у меня есть много таблиц, которые мне нужно создать, например, пользователи, клиенты, проекты, задачи, статусы, приоритеты, типы, команды. В идеале я хочу создать таблицы, которые содержат эти данные с внешними ключами, т.е.clients_projectproject_tasks т. И т. Д.

Надеюсь, кто-то может помочь мне начать.

001221
источник

Ответы:

357

Добавьте его в два этапа, и это тоже хорошо сделать без знака:

public function up()
{
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id')->unsigned();
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });

   Schema::table('priorities', function($table) {
       $table->foreign('user_id')->references('id')->on('users');
   });

}
Антонио Карлос Рибейро
источник
117
Спасибо Антонио! Для меня проблема не заключалась в добавлении unsigned () в столбец user_id, чтобы он соответствовал типу данных столбца id в таблице users. Функция Laravel increments ('id') создает целое число без знака, поэтому столбец внешнего ключа также должен быть без знака.
Брэд Гриффит
7
добавление неподписанного, кроме разделения на Schema::tableметод помогло! Спасибо!
patrickjason91
4
Для меня это не делало удостоверение личности также неподписанным. Спасибо за чаевые.
Карл Вейс
6
Решение в комментарии @BradGriffith. Как отмечалось выше, мне нет нужды отделяться вообще. Может быть, лучше обновить ответ соответственно.
Матания
12
Используйте, $table->unsignedBigInteger('user_id')если ваш user.idbigIncrements
Максим Иванов
114

Вопрос уже ответил, но надеюсь, что это может помочь кому-то еще.

Эта ошибка произошла для меня, потому что я создал таблицу миграции с внешним ключом, прежде чем ключ существовал в качестве первичного ключа в ее исходной таблице. Миграции выполняются в том порядке, в котором они были созданы, как указано именем файла, сгенерированным после запуска migrate:make. Например2014_05_10_165709_create_student_table.php .

Решением было переименовать файл с внешним ключом в более раннее время, чем файл с первичным ключом, как рекомендовано здесь: http://forumsarchive.laravel.io/viewtopic.php?id=10246

Я думаю, что я также должен был добавить в $table->engine = 'InnoDB';

haakym
источник
4
После того, как вы переименовали файл миграции и получили некоторые ошибки, такие как: Не удалось открыть поток: Нет такого файла или каталога (и отображается старое имя миграции), вы должны выполнить: composer dump-autoload
Stelian
14
$ table-> engine = 'InnoDB'; требуется для принудительного применения внешнего ключа на уровне MySql. Движок laravel по умолчанию - MyIsam, который не поддерживает внешние ключи!
Франсуа Бретон,
2
это сработало и для меня, спасибо. Но мне кажется немного странным, что так работает. Я имею в виду, это имеет смысл, но должен быть способ указать порядок выполнения миграции, отличающийся от ручного переименования файлов и определения фиктивных дат в процессе
allisius
2
Я пришел сюда не потому, что получал какие-либо ошибки, но я смог добавить неправильные значения в столбец, который был внешним ключом. Потом я увидел комментарий и ответ про InnoDB. Это было приятно знать. Спасибо, ребята :)
SuperNOVA
2
Порядок, в котором вы создали свои миграции, остается важным при миграции. Я столкнулся с этой проблемой, но это решило ее.
mugabits
60

Laravel ^ 5.8

Начиная с Laravel 5.8 , заглушки миграции по умолчанию используют метод bigIncrements для столбцов идентификаторов. Ранее столбцы идентификаторов создавались с использованием метода приращений.

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

Источник: Миграции и большие инкременты


пример

Представим, что вы создаете простое приложение на основе ролей, и вам нужно сослаться на user_id в таблице PIVOT "role_user" .

2019_05_05_112458_create_users_table.php

// ...

public function up()
{
    Schema::create('users', function (Blueprint $table) {

        $table->bigIncrements('id');

        $table->string('full_name');
        $table->string('email');
        $table->timestamps();
    });
}

2019_05_05_120634_create_role_user_pivot_table.php

// ...

public function up()
{
    Schema::create('role_user', function (Blueprint $table) {

        // this line throw QueryException "SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint..."
        // $table->integer('user_id')->unsigned()->index();

        $table->bigInteger('user_id')->unsigned()->index(); // this is working
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    });
}

Как вы можете видеть, закомментированная строка выдаст исключение запроса, потому что, как упоминалось в примечаниях по обновлению, столбцы внешнего ключа должны быть одного типа , поэтому вам нужно либо изменить внешний ключ (в данном примере это user_id ) на bigInteger в таблице role_user или измените метод bigIncrements на метод приращений в таблице users и используйте закомментированную строку в сводной таблице, решать вам.


Я надеюсь, что смог прояснить этот вопрос для вас.

chebaby
источник
1
Спасибо. Вы спасли мою жизнь. Следуя вашему объяснению, я изменил свой внешний ключ на bigInteger, как вы и предлагали. Schema::table('goal_objective', function (Blueprint $table) { $table->bigInteger('job_title_id')->after('target')->unsigned()->nullable(); $table->foreign('job_title_id')->references('id')->on('job_titles')->onDelete('set null'); } Это сработало. Спасибо.
Брюс Тонг
1
@BruceTong, я рад, что смог помочь.
Чебаби
1
Да, это самый актуальный ответ.
Мохд Абдул Муджиб
1
Этот ответ очень полезен.
Карим Пазоки
1
Лучший ответ. Спасибо
VishalParkash
49

В моем случае проблема заключалась в том, что в основной таблице уже были записи, и я заставлял новый столбец не иметь значение NULL. Поэтому добавление -> nullable () в новый столбец помогло. В примере вопроса будет что-то вроде этого:

$table->integer('user_id')->unsigned()->nullable();

или:

$table->unsignedInteger('user_id')->nullable();

Надеюсь, это кому-нибудь поможет!

AdrianCR
источник
Обратите внимание, что столбец «id» в вашей родительской таблице также должен быть без знака! Использование строки, такой как $ table-> increments ('id'); автоматически по умолчанию будет без знака.
Колин Стадиг,
Это сработало для меня. Я изменил тип данных идентификатора родительской таблицы с BigIncrements на приращения.
Эммануэль Бенсон
22

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

...
$table->bigIncrements('id');
...

Поэтому мне пришлось изменить тип столбца


$table->bigInteger('id');

заставить мою миграцию с внешним ключом работать.

Это с laravel 5.8.2

Daniele
источник
Поскольку столбец внешнего ключа должен иметь тот же тип столбца, на который он ссылается
Daniele
9
Это сработало для меня $ table-> unsignedBigInteger ('user_id'); в 5,5. *
Адам Виннипасс
У меня также была эта проблема с 5.8, это исправило ее для меня! Спасибо!
Майк Шевард
Спас меня от долгой ночи!
chq
19

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

Дальше больше:

Когда вы создаете миграцию, у нее есть отметка времени в начале. Допустим, вы создали кошку миграции, чтобы она выглядела 2015_08_19_075954_the_cats_time.phpи имела такой код

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TheCatsTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cat', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');  
            $table->date('date_of_birth');
            $table->integer('breed_id')->unsigned()->nullable(); 
        });

        Schema::table('cat', function($table) {
        $table->foreign('breed_id')->references('id')->on('breed');
      });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('cat');
    }
}

И после создания базовой таблицы вы создаете другую породу миграции, которая является дочерней таблицей, у которой есть своя собственная отметка времени и даты создания. Код будет выглядеть так:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class BreedTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('breed', function (Blueprint $table) {
             $table->increments('id');    
             $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('breed');
    }
}

Кажется, что обе таблицы верны, но при запуске php artisan migrate . Это вызовет исключение, потому что миграция сначала создаст базовую таблицу в вашей базе данных, потому что вы сначала создали эту миграцию, и наша базовая таблица имеет ограничение внешнего ключа, которое будет искать дочернюю таблицу, а дочерняя таблица не существует, что, вероятно, исключение..

Так:

Сначала создайте миграцию дочерней таблицы.

Создать миграцию базовой таблицы после создания дочерней миграции.

php ремесленник мигрировать.

сделано это будет работать

Vicky
источник
13

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

В папке database / migrations / ваше имя файла миграции имеет следующий формат: year_month_day_hhmmss_create_XXXX_table.php

Просто переименуйте файл создания пользователя, чтобы дата создания таблицы приоритетов таблицы была установлена ​​позже, чем дата пользователя (достаточно даже одной секунды позже)

LDT
источник
13

В laravel 5.8 users_table использует bigIncrements('id')тип данных для первичного ключа. Так что, когда вы хотите сослаться на ограничение внешнего ключа, ваш user_idстолбец должен быть unsignedBigInteger('user_id')типом.

Дхара Талавия
источник
Большое спасибо, я потратил час, пытаясь выяснить, почему внешний ключ вызывает исключение
Я. Баша,
10

У меня была та же проблема с использованием Laravel 5.8. После более пристального взгляда на документы по Laravel, более того, здесь Migrations & bigIncrements . Я решил это путем добавления первичных ключей "$ table-> bigIncrements ('id')" к каждой отдельной таблице, которая связана с таблицей "users" и ее ассоциациями, в моем случае с таблицей "role" . Наконец, у меня был «$ table-> unsignedBigInteger» для привязки ролей к пользователям («многие ко многим»), то есть к таблице «role_user» .

1. Users table

    Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

2. Roles Table
    Schema::create('roles', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->unique();
        $table->string('display_name')->nullable();
        $table->string('description')->nullable();
        $table->timestamps();
    });

3. Table role_user
Schema::create('role_user', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('role_id');
            $table->foreign('user_id')->references('id')->on('users')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->primary(['user_id', 'role_id']);
        });
Capfer
источник
9

У меня была эта проблема с laravel 5.8, и я исправил этот код, как показано здесь в документации по Laravel , куда бы я ни добавлял внешний ключ.

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

тогда я побежал $ php artisan migrate:refresh

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

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
});
Slycreator
источник
7

Использование Laravel 5.3 было той же проблемой.

Решением было использовать unsignedInteger вместо integer ('name') -> unsigned () .

Так вот что сработало

$table->unsignedInt('column_name');
$table->foreign('column_name')->references('id')->on('table_name');

Причина, по которой это сработало, заключается в том, что при использовании целого числа («имя») -> без знака столбец, созданный в таблице, имел длину 11, а при использовании unsigedInteger («имя») столбец имел длину 10.

Длина 10 - это длина для первичных ключей при использовании Laravel, поэтому длина столбцов совпадает.

Раду Дикэ
источник
Чувак, спасибо за то, что я собирался сдаться и запустить raw sql, как только что нашел твой пост. Мне придется больше узнать о том, почему первичный ключ laravel вынужден иметь длину 10, и если есть какая-либо причина, почему выполнение целого числа ('column') -> unsigned () должно отличаться от unsigedInteger ('column')
Арно Бушо
6

Эта ошибка произошла для меня, потому что - хотя таблица, которую я пытался создать, была InnoDB - внешняя таблица, к которой я пытался связать ее, была таблицей MyISAM!

bagnap
источник
MyISAM не поддерживает ограничения внешнего ключа. Вероятно, это сработало, потому что переключение на MyISAM привело к тому, что он полностью проигнорировал внешний ключ, который, вероятно, существовал по какой-то причине. Быть осторожен.
greggle138
5

Мы не можем добавлять отношения, пока не будут созданы связанные таблицы. Laravel запускает миграции по порядку файлов миграции. Поэтому, если вы хотите создать связь с таблицей, которая существует во 2-м файле миграции, это не удастся.

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

Schema::table('properties', function(Blueprint $table) {
        $table->foreign('user')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('area')->references('id')->on('areas')->onDelete('cascade');
        $table->foreign('city')->references('id')->on('cities')->onDelete('cascade');
        $table->foreign('type')->references('id')->on('property_types')->onDelete('cascade');
    });

    Schema::table('areas', function(Blueprint $table) {
        $table->foreign('city_id')->references('id')->on('cities')->onDelete('cascade');
    });
Паван Кумар
источник
1
как ты назвал файл? 9999_99_99_999999_create_foreign_keys.php?
Яннацци
добавление 9999_99_99_99999 к имени файла миграции - плохая идея, так как это испортит функцию отката.
Маулик Гангани
5

Имейте в виду: когда Laravel устанавливает таблицу, используя

$table->increments('id');

что является стандартным в большинстве миграций, это установит поле целого числа без знака. Поэтому при создании внешней ссылки из другой таблицы на это поле убедитесь, что в ссылочной таблице вы задали для поля значение UnsignedInteger, а не (как я предполагал, поле) UnsignedBigInteger.

Например: в файле миграции 2018_12_12_123456_create_users_table.php:

Schema::create('users', function (Blueprint $table){
    $table->increments('id');
    $table->string('name');
    $table->timestamps();

Затем в файле миграции 2018_12_12_18000000_create_permissions_table.php, который устанавливает внешнюю ссылку для пользователей:

Schema::create('permissions', function (Blueprint $table){
    $table->increments('id');
    $table->UnsignedInteger('user_id'); // UnsignedInteger = "increments" in users table
    $table->boolean('admin');
    $table->boolean('enabled');
    $table->timestamps();

    // set up relationship
    $table->foreign('user_id')->reference('id')->on('users')->onDelete('cascade');
}
bnoeafk
источник
5

Вы должны написать таким образом

public function up()
{
    Schema::create('transactions', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->float('amount', 11, 2);
        $table->enum('transaction type', ['debit', 'credit']);
        $table->bigInteger('customer_id')->unsigned();      
        $table->timestamps();                 
    });

    Schema::table('transactions', function($table) {
        $table->foreign('customer_id')
              ->references('id')->on('customers')
              ->onDelete('cascade');
    });     
}

Поле внешнего ключа должно быть без знака , надеюсь, это поможет !!

Махеш Ядав
источник
Не просто без знака, но когда он ссылается на столбец bigIncrements, он должен быть unsigedBigInteger
gondwe
4

Для добавления ограничения внешнего ключа в laravel у меня сработало следующее:

  1. Создайте столбец для внешнего ключа следующим образом:

    $ Table-> целое число ( 'column_name') -> без знака ();
  2. Добавление строки ограничения сразу после (1) т.е.

    $ Table-> целое число ( 'column_name') -> без знака ();
    $ Table-> иностранный ( 'column_name') -> ссылки ( 'pk_of_other_table') -> по ( 'other_table');
bmnepali
источник
3

я знаю, что это старый вопрос, но убедитесь, что если вы работаете со ссылками, то определен соответствующий движок поддержки. установить механизм innodb для обеих таблиц и один и тот же тип данных для ссылочных столбцов

$table->engine = 'InnoDB';
di3
источник
2

Введя здесь несколько лет спустя после первоначального вопроса, используя laravel 5.1, у меня была та же самая ошибка, поскольку мои миграции были произведены на компьютере с тем же кодом даты. Я просмотрел все предложенные решения, а затем провел рефакторинг, чтобы найти источник ошибок.

В следующих laracasts и при чтении этих постов я считаю, что правильный ответ похож на ответ Вики, за исключением того, что вам не нужно добавлять отдельный вызов схемы. Вам не нужно накрывать на стол Innodb, я полагаю, что сейчас это делает Laravel.

Миграции просто необходимо правильно рассчитать, что означает, что вы измените код даты вверх (позже) в имени файла для таблиц, для которых вам нужны внешние ключи. В качестве альтернативы или дополнения, опустите код даты для таблиц, которым не нужны внешние ключи.

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

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

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

Вот пример: файл 2016_01_18_999999_create_product_options_table. Для этого нужно создать таблицу продуктов. Посмотрите на имена файлов.

 public function up()
{
    Schema::create('product_options', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('product_attribute_id')->unsigned()->index();
        $table->integer('product_id')->unsigned()->index();
        $table->string('value', 40)->default('');
        $table->timestamps();
        //$table->foreign('product_id')->references('id')->on('products');
        $table->foreign('product_attribute_id')->references('id')->on('product_attributes');
        $table->foreign('product_id')->references('id')->on('products');


    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('product_options');
}

таблица продуктов: сначала необходимо выполнить миграцию. 2015_01_18_000000_create_products_table

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->increments('id');

        $table->string('style_number', 64)->default('');
        $table->string('title')->default('');
        $table->text('overview')->nullable();
        $table->text('description')->nullable();


        $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::drop('products');
}

И, наконец, в самом конце файл, который я временно использую для решения проблем, который я буду реорганизовывать при написании тестов для моделей, которые я назвал 9999_99_99_999999_create_foreign_keys.php. Эти ключи комментируются, когда я их вытащил, но вы поняли.

    public function up()
    {
//        Schema::table('product_skus', function ($table) {
//            $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
//    });

    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
//        Schema::table('product_skus', function ($table)
//        {
//            $table->dropForeign('product_skus_product_id_foreign');
//        });
Iannazzi
источник
2

Так просто !!!

если вы впервые создали 'priorities'файл миграции, Laravel сначала запустится, 'priorities'пока 'users'таблица не существует.

Как это может добавить отношение к таблице, которая не существует!

Решение: вытащить коды внешних ключей из 'priorities'таблицы. Ваш файл миграции должен быть таким:

введите описание изображения здесь

и добавьте в новый файл миграции, вот его имя create_prioritiesForeignKey_tableи добавьте эти коды:

public function up()
{        
    Schema::table('priorities', function (Blueprint $table) {          
        $table->foreign('user_id')
              ->references('id')
              ->on('users');                        
    });
}
йозеф
источник
2

удостоверьтесь, что ваш столбец foreing находится над широким диапазоном столбца ключа foreing

I означает, что ваш foreingkey (во второй таблице) должен быть того же типа, что и ваш ponter pricipal key (в первой таблице)

Ваш основной ключ указателя должен быть добавлен без знака, позвольте мне показать:

на вашей ПЕРВОЙ таблице миграции:

$table->increments('column_name'); //is INTEGER and UNSIGNED

на вашей ВТОРОЙ таблице миграции:

$table->integer('column_forein_name')->unsigned(); //this must be INTEGER and UNSIGNED
$table->foreign('column_forein_name')->references('column_name')->on('first_table_name');

ДРУГОЙ ПРИМЕР, ЧТОБЫ УВИДЕТЬ РАЗНИЦУ

на вашей ПЕРВОЙ таблице миграции:

$table->mediumIncrements('column_name'); //is MEDIUM-INTEGER and UNSIGNED

на вашей ВТОРОЙ таблице миграции:

$table->mediumInteger('column_forein_name')->unsigned(); //this must be MEDIUM-INTEGER and UNSIGNED
$table->foreign('column_forein_name')->references('column_name')->on('first_table_name');

ПОСМОТРЕТЬ ЧИСЛО MYSQL ТАБЛИЦА ДИАПАЗОНОВ

Рубен Руис
источник
2

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

Например, если одна таблица использует:

$table->engine = 'InnoDB';

А другой использует

$table->engine = 'MyISAM';

сгенерирует ошибку:

SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint

Вы можете исправить это, просто добавив InnoDB в конце создания таблицы следующим образом:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedInteger('business_unit_id')->nullable();

        $table->string('name', 100);

        $table->foreign('business_unit_id')
                ->references('id')
                ->on('business_units')
                ->onDelete('cascade');

        $table->timestamps();
        $table->softDeletes();
        $table->engine = 'InnoDB'; # <=== see this line
    });
}
erlandmuchasaj
источник
1

В моем случае я ссылался на целочисленный id столбец в строковом user_id столбце. Я изменился:

$table->string('user_id')

чтобы:

$table->integer('user_id')->unsigned();

Надеюсь, это поможет кому-то!

Рафаэль Рафатпана
источник
1

Суть в том, что внешний метод используется ALTER_TABLEдля преобразования ранее существующего поля во внешний ключ. Таким образом, вы должны определить тип таблицы, прежде чем применять внешний ключ. Тем не менее, это не должно быть в отдельном Schema::вызове. Вы можете сделать оба в рамках создания, как это:

public function up()
{
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

Также обратите внимание, что тип user_idустановлен в unsigned, чтобы соответствовать внешнему ключу.

Менашех
источник
1

Вы можете напрямую передать логический параметр в столбце целых чисел, говоря, что он должен быть без знака или нет. В laravel 5.4 следующий код решил мою проблему.

        $table->integer('user_id', false, true);

Здесь второй параметр false представляет, что он не должен быть автоинкрементным, а третий параметр true представляет, что он должен быть без знака. Вы можете сохранить ограничение внешнего ключа в той же миграции или отделить его. Это работает на обоих.

Мохит Сатиш Павар
источник
1

Если ни одно из приведенных выше решений не подходит для новичков, проверьте, имеют ли оба идентификатора одинаковый тип: оба являются integerили оба являютсяbigInteger ... Вы можете получить что-то вроде этого:

Основная таблица (пользователи, например)

$table->bigIncrements('id');

Детский стол (приоритеты например)

$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

Этот запрос не будет выполнен, потому что users.idявляется BIG INTEGERтогда, когда priorities.user_idявляется INTEGER.

Правильный запрос в этом случае будет следующим:

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Вайл Карим
источник
1

В моем случае это не сработало, пока я не запустил команду

composer dump-autoload

таким образом, вы можете оставить внешние ключи внутри схемы создания

public function up()
{
    //
     Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
 }

 /**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}
Владимир Салгуэро
источник
1

Это также может быть ваш заказ создания миграции. Если вы сначала создадите таблицу приоритетов, а затем таблицу пользователей, то это будет неправильно. Из-за первой миграции ищем таблицу пользователей. Таким образом, вы должны изменить порядок миграции на

app/database/migrations

каталог

Туран Заманлы
источник
1

Для меня столбец таблицы, на который ссылалась моя дочерняя таблица, не был проиндексирован.

Schema::create('schools', function (Blueprint $table) {
    $table->integer('dcid')->index()->unque();
    $table->integer('school_number')->index(); // The important thing is that this is indexed
    $table->string('name');
    $table->string('abbreviation');
    $table->integer('high_grade');
    $table->integer('low_grade');
    $table->timestamps();
    $table->primary('dcid');
});

Schema::create('students', function (Blueprint $table) {
      $table->increments('id');
      $table->integer('dcid')->index()->unique()->nullable();
      $table->unsignedInteger('student_number')->nullable();
      $table->integer('schoolid')->nullable();
      $table->foreign('schoolid')->references('school_number')->on('schools')->onDelete('set null');
      // ...
});

Не обращайте внимания на ужасные названия, это из другой ужасно разработанной системы.

Грант
источник
1

Иногда эта ошибка может возникать из-за последовательности миграций.

Как пользователи и порядок две таблицы

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

Решение: просто поместите таблицу обновления заказа под пользователями для обновления

Пример: в моем случае таблицы образования и университета Таблица образования

public function up()
{
    Schema::create('doc_education', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('uni_id')->unsigned()->nullable();
        $table->timestamps();
    });
}

В университете

    Schema::create('doc_universties', function (Blueprint $table) {
        $table->increments('id');
        $table->string('uni_name');
        $table->string('location')->nullable();
        $table->timestamps();

        //
    });



Schema::table('doc_education', function(Blueprint $table) {
        $table->foreign('uni_id')->references('id')
        ->on('doc_universties')->onDelete('cascade');
    });
BlockCode
источник
0

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

public function up()
{
    Schema::create('image_post', function (Blueprint $table) {
        $table->engine = 'InnoDB';
        $table->increments('id');
        $table->integer('image_id')->unsigned()->index();
        $table->integer('post_id')->unsigned()->index();
        $table->timestamps();
    });

    Schema::table('image_post', function($table) {
        $table->foreign('image_id')->references('id')->on('image')->onDelete('cascade');
        $table->foreign('post_id')->references('id')->on('post')->onDelete('cascade');
    });

}
Осси
источник