Миграция 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) references
cb_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
имя столбца важно.
Пусть следующие ресурсы утолят вашу жажду знаний:
-
id()
: https://laravel.com/docs/8.x/migrations#column-method-id -
foreignIdFor()
: https://laravel.com/api/8.x/Illuminate/Database/Schema/Blueprint.html -
cascadeOnDelete()
&cascadeOnUpdate()
: https://laravel.com/api/8.x/Illuminate/Database/Schema/ForeignKeyDefinition.html
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 поддерживает внешние ключи только при создании таблицы, а не при изменении таблиц.