Я пытаюсь создать внешние ключи в 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
и т.д.
Надеюсь, кто-то может помочь мне начать.
Спасибо заранее.
Добавьте его в два шага, и хорошо также сделать его неподписанным:
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');
});
}
Вопрос уже ответил, но надеюсь, что это может помочь кому-то другому.
Эта ошибка произошла для меня, потому что я создал таблицу миграции с внешним ключом в ней, прежде чем ключ существовал как первичный ключ в исходной таблице. Миграции выполняются в том порядке, в котором они были созданы, как указано в имени файла, сгенерированном после запуска migrate:make
. Например. 2014_05_10_165709_create_student_table.php
.
Решением было переименовать файл с внешним ключом в более раннее время, чем файл с первичным ключом, как рекомендуется здесь: http://forumsarchive.laravel.io/viewtopic.php?id=10246
Думаю, мне также пришлось добавить $table->engine = 'InnoDB';
В моем случае проблема заключалась в том, что в основной таблице уже были записи, и я заставлял новый столбец не быть NULL. Поэтому добавление → nullable() в новый столбец делало трюк. В вопросе пример будет примерно таким:
$table->integer('user_id')->unsigned()->nullable();
или
$table->unsignedInteger('user_id')->nullable();
Надеюсь, это поможет кому-то!
В моем случае проблема заключалась в том, чтобы с синхронизацией миграции быть осторожным, при создании миграций сначала создавайте дочернюю миграцию, чем базовую миграцию. Потому что, если вы сначала создадите базовую миграцию, у которой ваш внешний ключ будет искать дочернюю таблицу, и не будет таблицы, которая затем выдаст исключение.
Дальше больше:
Когда вы создаете миграцию, у нее есть timestamp в начале. Допустим, вы создали кошку миграции, поэтому она будет выглядеть как 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');
}
}
И после создания базовой таблицы вы создаете другую породу миграции, которая является дочерней таблицей, у которой есть своя собственная timestamp и даты создания. Код будет выглядеть так:
<?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 ремесленник мигрировать.
сделано это будет работать
В моем случае я просто изменяю миграцию заказа, выполняются вручную, поэтому сначала создаются пользователи таблицы.
В папке базы данных/миграции/ваше имя файла миграции имеет следующий формат: year_month_day_hhmmss_create_XXXX_table.php
Просто переименуйте созданный файл пользователя, чтобы дата создания таблицы приоритетов таблиц была установлена позже, чем дата пользователя (даже спустя одну секунду)
Мы не можем добавлять отношения, пока не будут созданы связанные таблицы. 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');
});
Для добавления ограничения внешнего ключа в laravel, для меня работало следующее:
Создайте столбец для внешнего ключа следующим образом:
$table->integer('column_name')->unsigned();
Добавление строки ограничения сразу после (1) i.e.
$table->integer('column_name')->unsigned(); $table->foreign('column_name')->references('pk_of_other_table')->on('other_table');
Использование Laravel 5.3 имело ту же проблему.
Решение заключалось в использовании unsignedInteger вместо integer ('name') → unsigned().
Так вот что работает
$table->unsignedInt('column_name');
$table->foreign('column_name')->references('id')->on('table_name');
Причиной этого было то, что при использовании integer ('name') → unsigned столбец, созданный в таблице, имел длину 11, но при использовании unsigedInteger ('name' ) столбец имел длину 10.
Длина 10 - это длина для первичных ключей при использовании Laravel, поэтому длина столбцов соответствует.
Я знаю, что это старый вопрос, но убедитесь, что если вы работаете со ссылками, определен правильный механизм поддержки. set engine innodb для обеих таблиц и того же типа данных для ссылочных столбцов
$table->engine = 'InnoDB';
убедитесь, что столбец foreing находится в широком диапазоне ключевых столбцов
Я имею в виду, что ваш foreingkey (во второй таблице) должен быть того же типа вашего основного ключа ponter (в первой таблице)
ваш главный ключ указателя должен быть добавлен беззнаковый метод, позвольте мне показать:
в таблице ПЕРВОЙ миграции:
$table->increments('column_name'); //is INTEGER and UNSIGNED
в таблице SECOND migration:
$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 migration:
$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');
Перейдя сюда через несколько лет после первоначального вопроса, используя 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');
// });
Эта ошибка возникла для меня, потому что - в то время как таблица, которую я пыталась создать, была InnoDB - внешняя таблица, которую я пыталась связать с ней, была таблицей MyISAM!
В моем случае это не сработало, пока я не запустил команду
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');
}
Я сошел с ума, у меня просто была опечатка:
unsinged()
вместо unsigned()
.
Вы можете напрямую передать логический параметр в столбце целых чисел, говоря, что он должен быть без знака или нет. В laravel 5.4 следующий код решил мою проблему.
$table->integer('user_id', false, true);
Здесь второй параметр false представляет, что он не должен быть автоинкрементным, а третий параметр true представляет, что он должен быть без знака. Вы можете сохранить ограничение внешнего ключа в той же миграции или отделить его. Это работает на обоих.
Так просто!!!
если ваш первый файл миграции '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');
});
}
В моем случае я забыл использовать скобки для ->unsigned()
, когда я определил столбец.
Код Worng: $table->integer('permission_id')->unsigned;
Истинный код: $table->integer('permission_id')->unsigned();
В моем случае я ссылался на столбец целочисленный id
столбца строка user_id
. Я изменил:
$table->string('user_id')
в
$table->integer('user_id')->unsigned();
Надеюсь, это поможет кому-то!
В моем случае миграция, ответственная за создание ссылочной таблицы, была выполнена неправильно, поэтому в базе данных не было таблицы, на которую мог бы ссылаться внешний ключ.
Проверьте, существует ли таблица, и если нет, проверьте миграцию этой таблицы.
Имейте в виду: когда 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');
}
Это также может быть ваш заказ создания миграции. Если вы сначала создадите таблицу приоритетов, а затем таблицу пользователей, то это будет неправильно. Из-за первой миграции ищем таблицу пользователей. Таким образом, вы должны изменить порядок миграции на
app/database/migrations
каталог
если вам нужно создать внешний ключ в таблице приоритетов, то
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Вы должны создать столбец без знака, чтобы он работал.
Это решило мою проблему
Таблица или индекс, на которые ссылается ограничение, еще не существует
как сказал @haakym, единственное, что вам нужно сделать, это переименовать имя в xxx_xx_xx_xxxxxx_create_users_table и установить более раннюю дату, чем xxx_xx_xx_xxxxxx_create_priorities_table
не забудьте использовать $table->engine = 'InnoDB';
если вы используете MySql, потому что MyISAM не поддерживает внешние ключи ограничения
Если ни одно из приведенных выше решений не bigInteger
для новичков, проверьте, имеют ли оба идентификатора одинаковый тип: оба являются 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');
Добавление к решению unsigned() при создании базы данных с использованием InnoDB в качестве движка таблиц. Убедитесь, что внешняя таблица была создана до таблиц, которые будут зависеть от внешней таблицы.
иллюстрация
Случай 1 (свежие таблицы)
Предположим, что ваша таблица комментариев зависит от таблицы сообщений (внешней таблицы). Вам необходимо создать таблицу сообщений перед созданием таблицы комментариев
Случай 2 (уже существующие таблицы)
Предположим, что ваша таблица комментариев была создана до вашей таблицы сообщений. Создайте свою таблицу записей в новом файле миграции, а затем добавьте внешние ключи таблицы комментариев в новый файл миграции, который вы создадите после создания миграции таблицы записей.
PS
Я полагаю, вы используете Laravel
Я думаю: ссылочным ключом должен быть "индекс". например: (вниз)
public function up()
{
Schema::create('clicks', function (Blueprint $table) {
$table->increments('id');
$table->string('viewer_id');
$table->integer('link_id')->index()->unsigned();
$table->string('time');
$table->timestamps();
});
Schema::table('clicks', function($table) {
$table->foreign('link_id')->references('id')->on('links')->onDelete('cascade');
});
}
удачи.
Суть заключается в том, что посторонний метод использует ALTER_TABLE
, чтобы сделать ранее существовавшее поле во внешнем ключе. Таким образом, вы должны определить тип таблицы, прежде чем применять внешний ключ. Однако он не должен быть в отдельном вызове Schema::
. Вы можете делать и то, и другое внутри create, например:
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 для соответствия внешнему ключу.
У меня была такая же ошибка с Laravel 5 при создании сводной таблицы, и проблема в моем случае состояла в том, что у меня не было
->onDelete('cascade');
Одна вещь, о которой я думаю, отсутствует в ответах здесь, и, пожалуйста, исправьте меня, если я ошибаюсь, но внешние ключи нужно индексировать на сводной таблице. По крайней мере, в 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');
});
}