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


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

Будь-які ідеї щодо того, що я зробив не так, я хочу зрозуміти це зараз, оскільки у мене є маса таблиць, які мені потрібно створити, наприклад, Користувачі, Клієнти, Проекти, Завдання, Статуси, Пріоритети, Типи, Команди. В ідеалі я хочу створити таблиці , які тримають ці дані з зовнішніми ключами, i..e clients_projectі project_tasksт.д.

Сподіваюся, хтось може допомогти мені почати.

Відповіді:


356

Додайте його в два кроки, і добре зробити так, щоб воно було і без підпису:

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
Спасибі, Антоніо! Для мене проблемою було не додавання неподписаного () у стовпчик user_id, щоб воно відповідало типу даних стовпця id у таблиці користувачів. Зростання функції Laravel ('id') створює непідписане ціле число, тому стовпець із зовнішнім ключем також повинен бути непідписаним.
Бред Гріффіт

7
додавання непідписаного, окрім поділу на Schema::tableметод допомогло! Дякую!
patrickjason91

4
Для мене це не робило ідентифікатор неподписаним. Дякую за пораду.
Карл Вайс

6
Рішення знаходиться у коментарі @BradGriffith. Як зазначалося вище, взагалі не потрібно розлучатися. Можливо, краще оновити відповідь відповідно.
Матанія

11
Використовуйте, $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';


4
Після перейменування файлу міграції та отримання помилок на кшталт: Не вдалося відкрити потік: Немає такого файлу чи каталогу (і відображається старе ім’я міграції), вам потрібно запустити: композитор dump-autoload
Stelian

14
$ table-> engine = 'InnoDB'; необхідний для забезпечення зовнішнього ключа на рівні MySql. За замовчуванням двигун laravel - MyIsam, який не підтримує сторонні ключі!
Франсуа Бретон

2
це працювало і для мене, дякую. Але мені здається трохи дивним, що це працює саме так. Я маю на увазі, це має сенс, але повинен бути спосіб вказати порядок виконання міграції, крім того, щоб перейменувати файли вручну та придумувати фальшиві дати в процесі
allisius

2
Я прийшов сюди не тому, що отримував помилки, але міг додати неправильні значення до стовпця, який був іноземним ключем. Тоді я побачив коментар та відповідь про InnoDB. Це було добре знати. Спасибі хлопці :)
SuperNOVA

2
Порядок, в якому ви створили міграцію, все ще залишається важливим під час міграції. Я зіткнувся з цим питанням, але це вирішило його.
мугабіти

60

Ларавель ^ 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 на метод приросту в таблиці користувачів та використовувати коментований рядок у зведеній таблиці, це залежить від вас.


Я сподіваюся, що мені вдалося прояснити це питання до вас.


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();

Сподіваюся, це комусь допоможе!


Зауважте, що стовпчик 'id' у батьківській таблиці також має бути непідписаним! Використання рядка, такого як $ table-> з кроком ('id'); автоматично за замовчуванням не підписаний.
Колін Стадіг

Це працювало для мене. Я змінив тип даних ідентифікатора батьківської таблиці з BigIncrements на збільшення.
Еммануель Бенсон

22

У моєму випадку проблема полягала в тому, що автоматично створена міграція для usersтаблиці встановлювалась

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

Тому мені довелося змінити тип стовпця


$table->bigInteger('id');

щоб змусити міграцію з іноземним ключовим твором.

Це з laravel 5.8.2


Оскільки стовпець із зовнішнім ключем повинен мати той самий тип стовпця, на який він посилається
Даніеле

9
Це працювало для мене $ table-> unsignedBigInteger ('user_id'); in laravel 5.8. *
Адам Вінніпас

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

Так:

Створіть спочатку міграцію дочірньої таблиці.

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

php ремісник мігрує.

зробили це буде працювати


13

У моєму випадку я просто змінюю порядок міграції виконуються вручну, щоб спочатку створювалися користувачі таблиці.

У базі даних / міграцій / ім'я міграційного файлу має такий формат: year_month_day_hhmmss_create_XXXX_table.php

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


13

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


велике спасибі, я витратив годину, намагаючись з'ясувати, чому зовнішній ключ викликає виняток
Я Баша,

10

У мене виникли ті ж проблеми, використовуючи Laravel 5.8. Ознайомившись детальніше з документами laravel, до того ж тут Міграції та великі Покращення . Я вирішив це шляхом додавання первинних ключів "$ table-> bigIncrements ('id") " до кожної таблиці, яка пов'язана з таблицею " користувачі " та її асоціаціями, в моєму випадку - таблицею " роль " . Нарешті, у мене був "$ table-> unsignedBigInteger" для асоціації ролей з користувачами (Many-to-Many), тобто таблиця "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']);
        });

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

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, тому довжина стовпців збігається.


Людина, дякую за те, що я збирався відмовитись і запустити сирий sql, коли я щойно знайшов твій пост. Мені доведеться прочитати докладніше про те, чому Laravel Первинний ключ змушений бути довжиною 10, і якщо є якась причина, чому виконання цілого ('стовпця') -> непідписаного () має відрізнятися від unsigedInteger ('стовпець')
Арно Бушо

6

Ця помилка трапилася для мене, оскільки - поки таблиця, яку я намагався створити, - InnoDB - зовнішня таблиця, яку я намагався пов’язати, - це таблиця MyISAM!


MyISAM не підтримує зовнішні ключові обмеження. Це, ймовірно, спрацювало, оскільки перехід на MyISAM змусив його повністю ігнорувати зовнішній ключ, який, мабуть, був там чомусь. Будь обережний.
greggle138

5

Ми не можемо додавати відносини, якщо не будуть створені відповідні таблиці. Laravel запускає порядок міграцій за датою файлів міграції. Отже, якщо ви хочете створити співвідношення з таблицею, яка існує у другому файлі міграції, це не вдасться.

Я зіткнувся з тією ж проблемою, тому я створив ще один файл міграції, нарешті, щоб вказати всі відносини.

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

додавання 9999_99_99_99999 до імені міграції файлів - це погана ідея, оскільки це призведе до того, що він накрутить функцію відката.
Maulik Gangani

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

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

Зовнішнє ключове поле має бути непідписаним , сподіваюся, що це допоможе !!


Не просто непідписаний, але коли він посилається на великий стовпчик з збільшенням, він повинен бути відзначенийBigInteger
gondwe

4

Для додавання обмежень для зовнішніх ключів у laravel мені працювало наступне:

  1. Створіть стовпчик із зовнішнім ключем наступним чином:

    $ table-> integer ('column_name') -> без підпису ();
  2. Додавання лінії обмеження відразу після (1), тобто

    $ table-> integer ('column_name') -> без підпису ();
    $ table-> іноземна ('ім'я_колонки') -> посилання ('pk_of_other_table') -> увімкнено ('other_table');

3

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

$table->engine = 'InnoDB';

2

Через декілька років після первинного запитання, використовуючи laravel 5.1, я зазнав такої ж помилки, що і мої міграції були створені комп'ютером із тим самим кодом дати. Я переглянув усі запропоновані рішення, потім відновив пошук джерела помилок.

У наступних програмах і читаючи ці повідомлення, я вважаю, що правильна відповідь схожа на відповідь Вікі, за винятком того, що вам не потрібно додавати окремий виклик схеми. Вам не потрібно встановлювати стіл на 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');
//        });

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

переконайтеся, що стовпець для передбачення перебуває у великій кількості шаблону ключа передбачення

Я маю на увазі, що ваша передня клавіша (у другій таблиці) повинна бути однаковою для вашого ключа, призначеного для понтера (у першій таблиці)

до вашого основного ключа вказівника потрібно додати неподписаний метод, дозвольте мені показати:

на вашій ПЕРШІй міграційній таблиці:

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

на вашій SECOND таблиці міграції:

$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

на вашій SECOND таблиці міграції:

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

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встановлено непідписане, щоб відповідати іноземному ключу.


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

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

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.