Migrasi: Tidak dapat menambahkan batasan kunci asing


207

Saya mencoba membuat kunci asing di Laravel namun ketika saya memigrasikan meja saya menggunakan artisansaya terlempar kesalahan berikut:

[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`))     

Kode migrasi saya demikian:

file migrasi prioritas

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

file migrasi pengguna

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

Setiap gagasan tentang apa yang telah saya lakukan salah, saya ingin mendapatkan ini sekarang, karena saya punya banyak tabel yang perlu saya buat misalnya Pengguna, Klien, Proyek, Tugas, Status, Prioritas, Jenis, Tim. Idealnya saya ingin membuat tabel yang menyimpan data ini dengan kunci asing, i..e clients_projectdan project_taskslain - lain

Semoga seseorang dapat membantu saya memulai.

Jawaban:


357

Tambahkan dalam dua langkah, dan bagus juga untuk membuatnya tidak ditandatangani:

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
Terima kasih, Antonio! Bagi saya masalahnya bukan menambahkan unsigned () pada kolom user_id sehingga cocok dengan tipe data kolom id pada tabel pengguna. Fungsi kenaikan Laravel ('id') menciptakan integer yang tidak ditandai, sehingga kolom kunci asing juga harus tidak ditandatangani.
Brad Griffith

7
menambahkan unsigned, selain memisahkan ke Schema::tablemetode membantu! Terima kasih!
patrickjason91

4
Bagi saya itu tidak membuat id juga. Terima kasih atas tipnya.
Carl Weis

6
Solusinya ada di komentar @BradGriffith. Seperti disebutkan di atas saya tidak perlu terpisah sama sekali. Mungkin lebih baik untuk memperbarui jawaban yang sesuai.
Matanya

11
Gunakan $table->unsignedBigInteger('user_id')jika user.id AndabigIncrements
Maksim Ivanov

114

Pertanyaan sudah dijawab, tetapi harap ini bisa membantu orang lain.

Kesalahan ini terjadi pada saya karena saya membuat tabel migrasi dengan kunci asing di dalamnya terlebih dahulu sebelum kunci tersebut ada sebagai kunci utama di tabel aslinya. Migrasi dieksekusi dalam urutan seperti yang ditunjukkan oleh nama file yang dihasilkan setelah dijalankan migrate:make. Misalnya 2014_05_10_165709_create_student_table.php.

Solusinya adalah mengubah nama file dengan kunci asing ke waktu yang lebih awal daripada file dengan kunci utama seperti yang direkomendasikan di sini: http://forumsarchive.laravel.io/viewtopic.php?id=10246

Saya pikir saya juga harus menambahkan $table->engine = 'InnoDB';


4
Setelah Anda mengganti nama file migrasi dan mendapatkan beberapa kesalahan seperti: Gagal membuka streaming: Tidak ada file atau direktori seperti itu (dan nama migrasi lama ditampilkan) Anda harus menjalankan: composer dump-autoload
Stelian

14
$ table-> engine = 'InnoDB'; diperlukan untuk menegakkan kunci asing di tingkat MySql. Mesin default laravel adalah MyIsam yang tidak mendukung kunci asing!
François Breton

2
ini juga bekerja untuk saya, terima kasih. Tapi rasanya agak aneh bagi saya bahwa ini bekerja dengan cara ini. Maksud saya, ini masuk akal, tetapi harus ada cara untuk menentukan urutan pelaksanaan migrasi selain mengubah nama file secara manual dan membuat tanggal palsu dalam proses
allisius

2
Saya datang ke sini bukan karena saya mendapatkan kesalahan, tapi saya bisa menambahkan nilai yang salah ke kolom yang merupakan kunci asing. Lalu saya melihat komentar dan jawaban tentang InnoDB. Ini bagus untuk diketahui. Terima kasih teman-teman :)
SuperNOVA

2
Urutan yang Anda buat untuk migrasi Anda masih tetap penting saat bermigrasi. Saya mengalami masalah ini tetapi ini menyelesaikannya.
mugabits

60

Laravel ^ 5.8

Pada Laravel 5.8 , bertopik migrasi menggunakan metode bigIncrements pada kolom ID secara default. Sebelumnya, kolom ID dibuat menggunakan metode kenaikan.

Ini tidak akan memengaruhi kode apa pun yang ada di proyek Anda; Namun, perlu diketahui bahwa kolom kunci asing harus dari jenis yang sama . Oleh karena itu, kolom yang dibuat menggunakan metode kenaikan tidak dapat merujuk kolom yang dibuat menggunakan metode bigIncrements.

Sumber: Migrasi & Investasi besar


Contoh

Bayangkan Anda sedang membangun aplikasi berbasis peran sederhana, dan Anda perlu mereferensikan user_id di tabel 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');
    });
}

Seperti yang Anda lihat, baris yang dikomentari akan mengeluarkan pengecualian permintaan, karena, seperti yang disebutkan dalam catatan pemutakhiran, kolom kunci asing harus dari jenis yang sama , oleh karena itu Anda perlu mengubah kunci foreing (dalam contoh ini adalah user_id ) untuk bigInteger di tabel role_user atau ubah metode bigIncrements menjadi metode penambahan di tabel pengguna dan gunakan baris yang dikomentari di tabel pivot, terserah Anda.


Saya harap saya bisa mengklarifikasi masalah ini kepada Anda.


1
Terima kasih. Anda menyelamatkan hidup saya. Setelah penjelasan Anda, saya mengubah kunci asing saya ke bigInteger seperti yang Anda sarankan. 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'); } Itu berhasil. Terima kasih.
Bruce Tong

1
@BruceTong, saya senang saya bisa membantu.
chebaby

1
Yup inilah jawaban yang paling relevan.
Mohd Abdul Mujib

1
Jawaban ini sangat membantu.
Karim Pazoki

1
Jawaban Terbaik. Terima kasih
VishalParkash

49

Dalam kasus saya, masalahnya adalah bahwa tabel utama sudah memiliki catatan di dalamnya dan saya memaksa kolom baru untuk tidak NULL. Jadi menambahkan -> nullable () ke kolom baru berhasil. Dalam contoh pertanyaan adalah kira-kira seperti ini:

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

atau:

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

Semoga ini bisa membantu seseorang!


Perhatikan bahwa kolom 'id' di tabel induk Anda juga harus tidak ditandatangani! Menggunakan baris seperti $ table-> increments ('id'); secara otomatis akan default ke unsigned.
Colin Stadig

Ini berhasil untuk saya. Saya mengubah tipe data id tabel induk dari BigIncrements ke peningkatan.
Emmanuel Benson

22

Dalam kasus saya masalahnya adalah bahwa migrasi yang dibuat secara otomatis untuk userstabel diatur

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

Jadi saya harus mengubah jenis kolom


$table->bigInteger('id');

untuk membuat migrasi saya dengan kunci asing berfungsi.

Ini dengan laravel 5.8.2


Karena kolom kunci asing harus memiliki jenis kolom yang sama dengan yang dimaksud
Daniele

9
Ini bekerja untuk saya $ table-> unsignedBigInteger ('user_id'); dalam laravel 5.8. *
Adam Winnipass

Saya juga memiliki masalah ini dengan 5.8, ini memperbaikinya untuk saya! Terima kasih!
Mike Sheward

Menyelamatkan saya dari malam yang panjang!
chq

19

Dalam kasus saya masalahnya adalah waktu migrasi berhati-hati saat membuat migrasi terlebih dahulu buat migrasi anak daripada migrasi dasar. Karena jika Anda membuat migrasi basis pertama yang memiliki kunci asing Anda akan mencari tabel anak dan tidak akan ada tabel yang kemudian melemparkan pengecualian.

Selanjutnya:

Saat Anda membuat migrasi, ia memiliki cap waktu di awal. katakanlah Anda telah membuat kucing migrasi sehingga akan terlihat seperti 2015_08_19_075954_the_cats_time.phpdan memiliki kode ini

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

Dan setelah membuat tabel dasar Anda membuat jenis migrasi lain yang merupakan tabel anak itu memiliki waktu pembuatan dan cap tanggal sendiri. Kode akan terlihat seperti:

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

tampaknya kedua tabel ini benar tetapi ketika Anda menjalankan php artisan migrasi . Ini akan mengeluarkan pengecualian karena migrasi pertama akan membuat tabel dasar dalam database Anda karena Anda telah membuat migrasi ini terlebih dahulu dan tabel dasar kami memiliki batasan kunci asing di dalamnya yang akan mencari tabel anak dan tabel anak tidak ada yang mungkin ada pengecualian ..

Begitu:

Buat migrasi tabel anak terlebih dahulu.

Buat migrasi tabel dasar setelah migrasi anak dibuat.

php tukang bermigrasi.

melakukannya akan berhasil


13

Dalam kasus saya, saya hanya mengubah urutan migrasi yang dieksekusi secara manual sehingga pengguna tabel dibuat terlebih dahulu.

Dalam database folder / migrasi / nama file migrasi Anda memiliki format ini: year_month_day_hhmmss_create_XXXX_table.php

Cukup ganti nama buat file pengguna sehingga tanggal pembuatan tabel prioritas tabel Anda ditetapkan lebih lambat dari tanggal pengguna (bahkan satu detik kemudian sudah cukup)


13

Di laravel 5.8, users_table menggunakan bigIncrements('id')tipe data untuk kunci utama. Sehingga ketika Anda ingin merujuk batasan kunci asing user_idkolom Anda harus unsignedBigInteger('user_id')mengetik.


terima kasih banyak, saya menghabiskan satu jam mencoba mencari tahu mengapa kunci asing menyebabkan pengecualian
Ya Basha

10

Saya mengalami masalah yang sama menggunakan Laravel 5.8. Setelah melihat lebih dekat ke dokumen laravel, apalagi di sini Migrasi & Instalasi Besar . Cara saya menyelesaikannya adalah dengan menambahkan kunci primer "$ table-> bigIncrements ('id')" ke setiap tabel yang terkait dengan tabel "pengguna" dan asosiasinya, dalam kasus saya tabel "peran" . Terakhir, saya memiliki "$ table-> unsignedBigInteger" untuk mengaitkan peran dengan pengguna (Banyak ke Banyak), yaitu, tabel "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

Saya punya masalah dengan laravel 5.8 dan saya memperbaiki kode ini, seperti yang ditunjukkan di sini dalam dokumentasi Laravel , di mana pun saya menambahkan kunci asing.

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

lalu aku berlari $ php artisan migrate:refresh

Karena sintaks ini agak bertele-tele, Laravel menyediakan metode terser tambahan yang menggunakan konvensi untuk memberikan pengalaman pengembang yang lebih baik. Contoh di atas dapat ditulis seperti ini:

Schema::table('posts', function (Blueprint $table) {
    $table->foreignId('user_id')->constrained()->onDelete('cascade');
});

7

Menggunakan Laravel 5.3 memiliki masalah yang sama.

Solusinya adalah menggunakan unsignedInteger alih-alih integer ('name') -> unsigned () .

Jadi ini yang berhasil

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

Alasan ini berhasil adalah kenyataan bahwa ketika menggunakan integer ('name') -> unsigned kolom yang dibuat dalam tabel memiliki panjang 11, tetapi ketika menggunakan unsigedInteger ('name') kolom tersebut memiliki panjang 10.

Panjang 10 adalah panjang untuk kunci utama saat menggunakan Laravel sehingga panjang kolom cocok.


Man, terima kasih untuk itu saya akan menyerah dan menjalankan sql mentah karena saya baru saja menemukan posting Anda. Saya harus membaca tentang mengapa kunci Primer laravel dibuat dengan panjang 10 dan jika ada alasan mengapa melakukan integer ('kolom') -> unsigned () harus berbeda dari unsigedInteger ('kolom')
Arnaud Bouchot

6

Kesalahan ini terjadi pada saya karena - sementara tabel yang saya coba buat adalah InnoDB - tabel asing yang saya coba kaitkan dengannya adalah tabel MyISAM!


MyISAM tidak mendukung batasan kunci asing. Ini mungkin berhasil karena beralih ke MyISAM menyebabkannya mengabaikan kunci asing yang mungkin ada karena suatu alasan. Hati-hati.
greggle138

5

Kami tidak dapat menambahkan hubungan, kecuali tabel terkait dibuat. Laravel menjalankan pesanan migrasi berdasarkan tanggal file migrasi. Jadi jika Anda ingin membuat hubungan dengan tabel yang ada di file migrasi ke-2, gagal.

Saya menghadapi masalah yang sama, jadi saya membuat satu file migrasi lagi untuk menentukan semua hubungan.

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
apa nama file itu? 9999_99_99_999999_create_foreign_keys.php?
Iannazzi

menambahkan 9999_99_99_99999 ke nama file migrasi adalah ide yang buruk karena akan mengacaukan fitur rollback.
Maulik Gangani

5

Berhati-hatilah: saat Laravel menyiapkan tabel menggunakan

$table->increments('id');

yang merupakan standar di sebagian besar migrasi, ini akan mengatur bidang bilangan bulat yang tidak ditandatangani. Oleh karena itu saat membuat referensi asing dari tabel lain ke bidang ini, pastikan bahwa dalam tabel referensi, Anda menetapkan bidang ke UnsignedInteger dan bukan (yang saya anggap sebagai) bidang UnsignedBigInteger.

Misalnya: di file migrasi 2018_12_12_123456_create_users_table.php:

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

Kemudian di file migrasi 2018_12_12_18000000_create_permissions_table.php, yang mengatur referensi asing kembali ke pengguna:

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

Anda harus menulis dengan cara ini

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

Bidang kunci asing harus ditandatangani , semoga membantu !!


Bukan hanya unsigned tetapi ketika referensi kolomIninstal besar, itu harus unsigedBigInteger
gondwe

4

Untuk membuat penambahan batasan kunci asing di laravel, berikut ini bekerja untuk saya:

  1. Buat kolom menjadi kunci asing sebagai berikut:

    $ table-> integer ('column_name') -> unsigned ();
  2. Menambahkan garis kendala segera setelah (1) yaitu

    $ table-> integer ('column_name') -> unsigned ();
    $ table-> foreign ('column_name') -> referensi ('pk_of_other_table') -> on ('other_table');

3

Saya tahu itu pertanyaan lama tetapi pastikan jika Anda bekerja dengan referensi mesin pendukung yang tepat didefinisikan. atur mesin innodb untuk kedua tabel dan tipe data yang sama untuk kolom referensi

$table->engine = 'InnoDB';

2

Menjebak di sini beberapa tahun setelah pertanyaan awal, menggunakan laravel 5.1, saya memiliki kesalahan yang sama dengan migrasi saya yang dihasilkan komputer dengan semua kode tanggal yang sama. Saya memeriksa semua solusi yang diusulkan, kemudian refactored untuk menemukan sumber kesalahan.

Dalam laracasts berikut, dan dalam membaca posting ini, saya percaya jawaban yang benar mirip dengan jawaban Vickies, dengan pengecualian bahwa Anda tidak perlu menambahkan panggilan skema terpisah. Anda tidak perlu mengatur meja ke Innodb, saya berasumsi laravel sekarang melakukan itu.

Migrasi hanya perlu diatur waktunya dengan benar, yang berarti Anda akan mengubah kode tanggal naik (nanti) dalam nama file untuk tabel di mana Anda memerlukan kunci asing. Atau sebagai tambahan, Turunkan datecode untuk tabel yang tidak memerlukan kunci asing.

Keuntungan dalam memodifikasi datecode adalah kode migrasi Anda akan lebih mudah dibaca dan dipelihara.

Sejauh ini kode saya berfungsi dengan menyesuaikan kode waktu ke atas untuk mendorong kembali migrasi yang memerlukan kunci asing.

Namun saya punya ratusan meja, jadi pada akhirnya saya punya satu meja terakhir hanya untuk kunci asing. Hanya untuk membuat segalanya mengalir. Saya berasumsi saya akan menarik mereka ke file yang benar dan memodifikasi datecode saat saya mengujinya.

Jadi contoh: file 2016_01_18_999999_create_product_options_table. Yang ini membutuhkan tabel produk yang akan dibuat. Lihatlah nama file.

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

tabel produk: ini perlu dimigrasi dulu. 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');
}

Dan akhirnya di bagian paling akhir file yang saya gunakan sementara untuk menyelesaikan masalah, yang akan saya refactor ketika saya menulis tes untuk model yang saya beri nama 9999_99_99_999999_create_foreign_keys.php. Kunci-kunci ini dikomentari ketika saya mengeluarkannya, tetapi Anda mengerti maksudnya.

    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

Sangat sederhana !!!

jika Anda pertama kali membuat 'priorities'file migrasi, Laravel jalankan dulu 'priorities'sementara 'users'tabel tidak ada.

bagaimana bisa menambahkan relasi ke tabel yang tidak ada !.

Solusi: mengeluarkan kode kunci asing dari 'priorities'tabel. file migrasi Anda harus seperti ini:

masukkan deskripsi gambar di sini

dan tambahkan ke file migrasi baru, ini namanya create_prioritiesForeignKey_tabledan tambahkan kode-kode ini:

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

2

pastikan kolom foreing Anda lebih luas dari foreing key key

Maksud saya foreingkey Anda (di tabel kedua) harus sama jenis kunci pricipal ponter Anda (di tabel pertama)

kunci utama penunjuk Anda harus ditambahkan metode yang tidak ditandatangani, izinkan saya menunjukkan:

pada tabel migrasi PERTAMA Anda:

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

pada tabel migrasi KEDUA Anda:

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

CONTOH LAIN UNTUK MELIHAT PERBEDAAN

pada tabel migrasi PERTAMA Anda:

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

pada tabel migrasi KEDUA Anda:

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

MELIHAT MYSQL NUMERIC TYPE TABLE RANGES


2

Satu hal yang saya perhatikan adalah bahwa jika tabel menggunakan mesin yang berbeda dari batasan kunci asing tidak berfungsi.

Misalnya jika satu tabel menggunakan:

$table->engine = 'InnoDB';

Dan kegunaan lainnya

$table->engine = 'MyISAM';

akan menghasilkan kesalahan:

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

Anda bisa memperbaikinya dengan hanya menambahkan InnoDB di akhir pembuatan tabel Anda seperti:

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

Dalam kasus saya, saya mereferensikan kolom integer id pada kolom string user_id . Aku berubah:

$table->string('user_id')

untuk:

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

Semoga ini bisa membantu seseorang!


1

Intinya adalah bahwa metode asing digunakan ALTER_TABLEuntuk membuat bidang yang sudah ada menjadi kunci asing. Jadi, Anda harus menentukan tipe tabel sebelum Anda menerapkan kunci asing. Namun, itu tidak harus dalam Schema::panggilan terpisah . Anda dapat melakukan keduanya di dalam buat, seperti ini:

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

Perhatikan juga bahwa tipe user_iddiset ke unsigned agar cocok dengan kunci asing.


1

Anda dapat langsung melewati parameter boolean di kolom integer yang mengatakan bahwa itu harus tidak ditandatangani atau tidak. Di laravel 5.4 kode berikut memecahkan masalah saya.

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

Di sini parameter kedua false menyatakan bahwa seharusnya tidak bertambah secara otomatis dan parameter ketiga true menyatakan bahwa seharusnya tidak ditandatangani. Anda dapat menjaga batasan kunci asing dalam migrasi yang sama atau memisahkannya. Ini bekerja pada keduanya.


1

Jika tidak ada solusi di atas yang berfungsi untuk pemula, periksa apakah kedua ID memiliki tipe yang sama: keduanya integeratau keduanyabigInteger , ... Anda dapat memiliki sesuatu seperti ini:

Tabel Utama (pengguna misalnya)

$table->bigIncrements('id');

Meja Anak (prioritas misalnya)

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

Kueri ini akan gagal karena users.idmerupakan BIG INTEGERsedangkan priorities.user_idadalah INTEGER.

Kueri yang tepat dalam kasus ini adalah sebagai berikut:

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

1

Dalam kasus saya itu tidak berfungsi sampai saya menjalankan perintah

composer dump-autoload

dengan begitu Anda bisa meninggalkan kunci asing di dalam Skema buat

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

Mungkin juga Anda memesan migrasi kreasi. Jika Anda pertama kali membuat tabel prioritas, dan setelah tabel pengguna maka itu akan salah. Karena migrasi pertama mencari tabel pengguna. Jadi, Anda harus mengubah urutan migrasi

app/database/migrations

direktori


1

Bagi saya, kolom tabel yang direferensikan oleh tabel anak saya tidak diindeks.

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

Abaikan penamaan yang mengerikan, itu dari sistem lain yang dirancang sangat.


1

Beberapa kali kesalahan ini dapat terjadi karena urutan migrasi.

Seperti Pengguna dan Pesanan adalah dua tabel

Tabel pesanan memiliki kunci asing pengguna (Selama migrasi jika Tabel pesanan dimigrasi terlebih dahulu maka itu akan menyebabkan masalah karena tidak ada pengguna yang cocok dengan kunci asing)

Solusi: Taruh saja tabel Pembaruan Pesanan di bawah pengguna untuk pembaruan

Contoh: Dalam kasus saya Tabel Pendidikan dan Universitas Tabel Pendidikan

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

Di Universitas

    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

Satu hal yang menurut saya hilang dari jawaban di sini, dan tolong perbaiki saya jika saya salah, tetapi kunci asing perlu diindeks pada tabel pivot. Setidaknya dalam mysql yang tampaknya menjadi masalah.

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

}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.