Di chuyển: Không thể thêm ràng buộc khóa ngoại


206

Tôi đang cố gắng tạo khóa ngoại trong Laravel tuy nhiên khi tôi di chuyển bảng của mình bằng cách sử dụng thì artisantôi đã gặp phải lỗi sau:

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

Mã di chuyển của tôi là như vậy:

tập tin di chuyển ưu tiên

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

tập tin người dùng di chuyển

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

Bất kỳ ý tưởng nào về những gì tôi đã làm sai, tôi muốn có được điều này ngay bây giờ, vì tôi đã có rất nhiều bảng tôi cần tạo, ví dụ: Người dùng, Khách hàng, Dự án, Nhiệm vụ, Trạng thái, Ưu tiên, Loại, Nhóm. Lý tưởng nhất là tôi muốn tạo các bảng chứa dữ liệu này bằng các khóa ngoại, i..e clients_projectproject_tasksv.v.

Hy vọng ai đó có thể giúp tôi bắt đầu.

Câu trả lời:


356

Thêm vào hai bước và thật tốt khi làm cho nó không dấu:

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
Cảm ơn, Antonio! Đối với tôi, vấn đề không phải là không dấu () trên cột user_id để nó khớp với kiểu dữ liệu của cột id trên bảng người dùng. Hàm số gia ('id') của Laravel tạo ra một số nguyên không dấu, do đó, cột khóa ngoài cũng cần phải được ký.
Brad Griffith

7
thêm không dấu, ngoài việc tách ra để Schema::tablegiúp phương pháp! Cảm ơn!
patrickjason91

4
Đối với tôi nó không làm cho id không dấu là tốt. Cảm ơn vì tiền hỗ trợ.
Carl Weis

6
Giải pháp là trong bình luận của @BradGriffith. Như đã nói ở trên tôi không cần phải tách ra chút nào. Có lẽ tốt hơn để cập nhật câu trả lời cho phù hợp.
Matanya

11
Sử dụng $table->unsignedBigInteger('user_id')nếu user.id của bạn làbigIncrements
Maksim Ivanov

114

Câu hỏi đã được trả lời, nhưng hy vọng điều này có thể giúp người khác.

Lỗi này xảy ra với tôi vì trước tiên tôi đã tạo bảng di chuyển có khóa ngoại trước khi khóa tồn tại dưới dạng khóa chính trong bảng gốc. Di chuyển được thực hiện theo thứ tự chúng được tạo như được chỉ định bởi tên tệp được tạo sau khi chạy migrate:make. Ví dụ 2014_05_10_165709_create_student_table.php.

Giải pháp là đổi tên tệp có khóa ngoại thành thời gian sớm hơn tệp có khóa chính như được đề xuất ở đây: http://forumsarchive.laravel.io/viewtopic.php?id=10246

Tôi nghĩ rằng tôi cũng đã phải thêm vào $table->engine = 'InnoDB';


4
Sau khi bạn đổi tên tệp di chuyển và gặp một số lỗi như: Không thể mở luồng: Không có tệp hoặc thư mục đó (và tên di chuyển cũ được hiển thị), bạn phải chạy: trình soạn thảo dump-autoload
Stelian

14
$ bảng-> engine = 'InnoDB'; được yêu cầu thực thi khóa ngoại ở cấp MySql. Công cụ laravel mặc định là MyIsam không hỗ trợ khóa ngoại!
François Breton

2
điều này làm việc cho tôi là tốt, cảm ơn. Nhưng có vẻ hơi lạ với tôi rằng nó hoạt động theo cách này. Ý tôi là, nó có ý nghĩa, nhưng nên có một cách để xác định thứ tự thực hiện di chuyển ngoài việc đổi tên thủ công các tệp và đến ngày giả trong quy trình
allisius

2
Tôi đến đây không phải vì tôi gặp bất kỳ lỗi nào, nhưng tôi có thể thêm các giá trị sai vào cột là khóa ngoại. Sau đó, tôi thấy bình luận và trả lời về InnoDB. Điều này là tốt để biết. Cảm ơn mọi người :)
SuperNOVA

2
Thứ tự mà bạn đã tạo di chuyển của mình vẫn còn quan trọng khi di chuyển. Tôi gặp vấn đề này nhưng điều này đã giải quyết nó.
Mugabits

60

Ấu trùng ^ 5,8

Kể từ phiên bản Laravel 5.8 , các sơ đồ di chuyển sử dụng phương thức bigIncrements trên các cột ID theo mặc định. Trước đây, các cột ID được tạo bằng phương pháp gia tăng.

Điều này sẽ không ảnh hưởng đến bất kỳ mã hiện có trong dự án của bạn; tuy nhiên, lưu ý rằng các cột khóa ngoại phải cùng loại . Do đó, một cột được tạo bằng phương pháp gia tăng không thể tham chiếu một cột được tạo bằng phương thức bigIncrements.

Nguồn: Di chuyển & bigIncrements


Thí dụ

Hãy tưởng tượng bạn đang xây dựng một ứng dụng dựa trên vai trò đơn giản và bạn cần tham chiếu user_id trong bảng 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_p 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');
    });
}

Như bạn có thể thấy, dòng nhận xét sẽ đưa ra một ngoại lệ truy vấn, bởi vì, như đã đề cập trong ghi chú nâng cấp, các cột khóa ngoại phải cùng loại , do đó bạn cần thay đổi khóa foraway (trong ví dụ này là user_id ) thành bigInteger trong bảng Role_user hoặc thay đổi phương thức bigIncrements thành phương thức gia tăng trong bảng người dùng và sử dụng dòng nhận xét trong bảng xoay vòng, tùy thuộc vào bạn.


Tôi hy vọng tôi đã có thể làm rõ vấn đề này với bạn.


1
Cảm ơn bạn. bạn đã cứu cuộc đời tôi. Theo lời giải thích của bạn, tôi đã thay đổi khóa ngoại của mình thành bigInteger như bạn đề xuất. 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'); } Nó đã làm việc. Cảm ơn bạn.
Bruce Tong

1
@BruceTong, tôi rất vui vì tôi đã có thể giúp đỡ.
chebaby

1
Yup đây là câu trả lời phù hợp nhất.
Mohd Abdul Mujib

1
Câu trả lời này rất hữu ích.
Karim Pazoki

1
Câu trả lời tốt nhất. Cảm ơn bạn
VishalParkash

49

Trong trường hợp của tôi, vấn đề là bảng chính đã có các bản ghi trong đó và tôi đã buộc cột mới không phải là NULL. Vì vậy, việc thêm một -> nullable () vào cột mới đã thực hiện thủ thuật. Trong ví dụ của câu hỏi sẽ là một cái gì đó như thế này:

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

hoặc là:

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

Hy vọng điều này sẽ giúp ai đó!


Lưu ý rằng cột 'id' trong bảng cha của bạn cũng cần được bỏ dấu! Sử dụng một dòng như $ bảng-> gia số ('id'); sẽ tự động mặc định để không dấu.
Colin Stadig

Điều này làm việc cho tôi. Tôi đã thay đổi kiểu dữ liệu của id bảng cha từ BigIncrements thành số gia.
Emmanuel Benson

22

Trong trường hợp của tôi, vấn đề là việc di chuyển được tạo tự động cho usersbảng đã được đặt

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

Vì vậy, tôi đã phải thay đổi loại cột


$table->bigInteger('id');

để làm cho việc di chuyển của tôi với công việc khóa ngoại.

Điều này với laravel 5.8.2


Bởi vì cột khóa ngoại phải có cùng loại cột mà nó đề cập đến
Daniele

9
Điều này làm việc cho tôi $ bảng-> unsignBigInteger ('user_id'); trong laravel 5,8. *
Adam Winnipass 16/03/19

Tôi cũng có vấn đề này với 5,8, điều này đã khắc phục nó cho tôi! Cảm ơn!
Mike Sheward

Cứu tôi khỏi một đêm dài!
chq

19

Trong trường hợp của tôi, vấn đề với thời gian di chuyển, hãy cẩn thận trong khi tạo di chuyển trước tiên tạo di chuyển con so với di chuyển cơ sở. Bởi vì nếu bạn tạo di chuyển cơ sở trước tiên có khóa ngoại của bạn sẽ tìm bảng con và sẽ không có bảng nào sau đó ném ngoại lệ.

Hơn nữa:

Khi bạn tạo di chuyển, nó có dấu thời gian ở đầu. giả sử bạn đã tạo một con mèo di chuyển để nó trông như thế 2015_08_19_075954_the_cats_time.phpvà nó có mã này

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

Và sau khi tạo bảng cơ sở, bạn tạo một giống di chuyển khác là bảng con, nó có dấu thời gian và ngày tạo riêng. Mã sẽ trông như sau:

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

Có vẻ như cả hai bảng này đều đúng nhưng khi bạn chạy php artisan di chuyển . Nó sẽ đưa ra một ngoại lệ vì trước tiên di chuyển sẽ tạo bảng cơ sở trong cơ sở dữ liệu của bạn vì bạn đã tạo di chuyển này trước tiên và bảng cơ sở của chúng tôi có ràng buộc khóa ngoại trong đó sẽ tìm bảng con và bảng con không tồn tại. một ngoại lệ..

Vì thế:

Tạo di chuyển bảng con đầu tiên.

Tạo di chuyển bảng cơ sở sau khi di chuyển con được tạo.

Nghệ nhân php di cư.

xong rồi nó sẽ làm việc


13

Trong trường hợp của tôi, tôi chỉ thay đổi việc di chuyển thứ tự được thực hiện thủ công để người dùng bảng được tạo trước.

Trong cơ sở dữ liệu thư mục / di chuyển / tên tệp di chuyển của bạn có định dạng này: year_month_day_hhmmss_create_XXXX_table.php

Chỉ cần đổi tên tạo tệp người dùng để ngày tạo của bảng ưu tiên bảng của bạn được đặt muộn hơn ngày người dùng (thậm chí một giây sau là đủ)


13

Trong laravel 5.8, users_table sử dụng bigIncrements('id')kiểu dữ liệu cho khóa chính. Vì vậy, khi bạn muốn giới thiệu một khóa ngoại, ràng buộc user_idcột của bạn cần phải được unsignedBigInteger('user_id')gõ.


cảm ơn bạn rất nhiều, tôi đã dành một giờ để cố gắng tìm hiểu tại sao khóa ngoại lại gây ra ngoại lệ
Ya Basha

10

Tôi đã gặp vấn đề tương tự khi sử dụng Laravel 5.8. Sau khi xem xét kỹ hơn về tài liệu laravel, hơn nữa ở đây Di chuyển & bigIncrements . Cách tôi giải quyết là bằng cách thêm các khóa chính "$ bảng-> bigIncrements ('id')" vào mỗi bảng có liên quan đến bảng "người dùng" và các liên kết của nó, trong trường hợp của tôi là "vai trò" của bảng . Cuối cùng, tôi đã có "$ bảng-> unsignBigInteger" để liên kết vai trò với người dùng (Nhiều-nhiều), nghĩa là bảng "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

Tôi gặp vấn đề này với laravel 5.8 và tôi đã sửa mã này, như được hiển thị ở đây trong tài liệu của Laravel , đến nơi tôi đang thêm khóa ngoại.

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

sau đó tôi chạy $ php artisan migrate:refresh

Vì cú pháp này khá dài dòng, nên Laravel cung cấp các phương thức bổ sung, chặt chẽ hơn, sử dụng quy ước để cung cấp trải nghiệm tốt hơn cho nhà phát triển. Ví dụ trên có thể được viết như vậy:

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

7

Sử dụng Laravel 5.3 có cùng một vấn đề.

Giải pháp là sử dụng unsignInteger thay cho số nguyên ('name') -> unsign () .

Vì vậy, đây là những gì đã làm việc

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

Lý do điều này hoạt động là vì khi sử dụng số nguyên ('name') -> không dấu , cột được tạo trong bảng có độ dài 11, nhưng khi sử dụng unsigedInteger ('name') , cột có độ dài 10.

Độ dài 10 là chiều dài cho các khóa chính khi sử dụng Laravel để độ dài cột khớp với nhau.


Man, cảm ơn bạn vì tôi đã từ bỏ và chạy sql thô khi tôi vừa tìm thấy bài viết của bạn. Tôi sẽ phải đọc thêm về lý do tại sao Khóa chính laravel bị buộc phải có độ dài 10 và nếu có bất kỳ lý do nào khiến việc thực hiện số nguyên ('cột') -> unsign () nên khác với unsigedInteger ('cột')
Arnaud Bouchot

6

Lỗi này xảy ra với tôi vì - trong khi bảng tôi đang cố tạo là InnoDB - bảng ngoại tôi đang cố liên kết nó là bảng MyISAM!


MyISAM không hỗ trợ các ràng buộc khóa ngoài. Nó có khả năng hoạt động vì chuyển sang MyISAM khiến nó hoàn toàn bỏ qua khóa ngoại có lẽ là có lý do. Hãy cẩn thận.
greggle138

5

Chúng tôi không thể thêm quan hệ, trừ khi các bảng liên quan được tạo. Laravel chạy thứ tự di chuyển theo ngày của các tệp di chuyển. Vì vậy, nếu bạn muốn tạo một mối quan hệ với một bảng tồn tại trong tệp di chuyển thứ 2 thì nó không thành công.

Tôi đã đối mặt với cùng một vấn đề, vì vậy cuối cùng tôi đã tạo thêm một tệp di chuyển để chỉ định tất cả các quan hệ.

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
bạn đã đặt tên cho tập tin là gì? 9999_99_99_999999_create_forign_keys.php?
Iannazzi

thêm 9999_99_99_99999 vào tên tệp di chuyển là ý tưởng tồi vì nó sẽ làm hỏng tính năng rollback.
Maulik Gangani

5

Lưu ý: khi Laravel thiết lập bảng bằng cách sử dụng

$table->increments('id');

là tiêu chuẩn trong hầu hết các lần di chuyển, điều này sẽ thiết lập trường số nguyên không dấu. Do đó, khi tạo một tham chiếu nước ngoài từ một bảng khác đến trường này, hãy đảm bảo rằng trong bảng tham chiếu, bạn đặt trường thành UnsignInteger chứ không phải (cái mà tôi cho là một trường) UnsignBigInteger.

Ví dụ: trong tệp di chuyển 2018_12_12_123456_create_users_table.php:

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

Sau đó, trong tệp di chuyển 2018_12_12_18000000_create_permissions_table.php, thiết lập tham chiếu nước ngoài trở lại cho người dùng:

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

Bạn nên viết theo cách này

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

Trường khóa ngoại nên không dấu , hy vọng nó có ích !!


Không chỉ không dấu mà khi nó tham chiếu một cột bigIncrements, nó sẽ là unigedBigInteger
gondwe

4

Để bổ sung các ràng buộc khóa ngoại trong laravel, cách sau đây có hiệu quả với tôi:

  1. Tạo cột là khóa ngoại như sau:

    $ bảng-> số nguyên ('cột_name') -> unsign ();
  2. Thêm dòng ràng buộc ngay sau (1) tức là

    $ bảng-> số nguyên ('cột_name') -> unsign ();
    $ bảng-> nước ngoài ('cột_name') -> tài liệu tham khảo ('pk_of_other_table') -> on ('other_table');

3

Tôi biết đó là một câu hỏi cũ nhưng đảm bảo nếu bạn đang làm việc với các tham chiếu thì công cụ hỗ trợ phù hợp được xác định. đặt công cụ innodb cho cả hai bảng và cùng loại dữ liệu cho các cột tham chiếu

$table->engine = 'InnoDB';

2

Một vài năm sau câu hỏi ban đầu, sử dụng laravel 5.1, tôi đã gặp lỗi tương tự như việc di chuyển của tôi là máy tính được tạo ra với tất cả cùng một mã ngày. Tôi đã đi qua tất cả các giải pháp được đề xuất, sau đó tái cấu trúc để tìm nguồn lỗi.

Trong các lần theo dõi và đọc các bài đăng này, tôi tin rằng câu trả lời đúng tương tự như câu trả lời của Vickies, ngoại trừ việc bạn không cần thêm một lệnh gọi lược đồ riêng. Bạn không cần phải đặt bàn thành Innodb, tôi cho rằng laravel hiện đang làm điều đó.

Việc di chuyển chỉ cần được định thời gian chính xác, điều đó có nghĩa là bạn sẽ sửa đổi mã ngày tháng (sau này) trong tên tệp cho các bảng mà bạn cần khóa ngoại. Ngoài ra, ngoài ra, hãy hạ thấp mã dữ liệu cho các bảng không cần khóa ngoại.

Ưu điểm trong việc sửa đổi mã dữ liệu là mã di chuyển của bạn sẽ dễ đọc và duy trì hơn.

Cho đến nay, mã của tôi đang hoạt động bằng cách điều chỉnh mã thời gian lên để đẩy lùi việc di chuyển cần khóa ngoại.

Tuy nhiên, tôi có hàng trăm bảng, vì vậy cuối cùng tôi có một bảng cuối cùng chỉ cho các khóa ngoại. Chỉ để mọi thứ trôi chảy. Tôi giả sử tôi sẽ kéo chúng vào đúng tệp và sửa đổi mã dữ liệu khi tôi kiểm tra chúng.

Vì vậy, một ví dụ: tệp 2016_01_18_999999_create_product_options_table. Điều này cần bảng sản phẩm được tạo ra. Nhìn vào tên tập tin.

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

bảng sản phẩm: cái này cần di chuyển trước. 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');
}

Và cuối cùng, cuối cùng tập tin mà tôi đang tạm thời sử dụng để giải quyết các vấn đề, tôi sẽ cấu trúc lại khi tôi viết bài kiểm tra cho các mô hình mà tôi đặt tên là 9999_99_99_999999_create_forign_keys.php. Các phím này được nhận xét khi tôi kéo chúng ra, nhưng bạn nhận được điểm.

    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

Quá đơn giản !!!

nếu lần đầu tiên tạo 'priorities'tệp di chuyển của bạn , lần đầu tiên Laravel chạy 'priorities'trong khi 'users'bảng không tồn tại.

làm thế nào nó có thể thêm quan hệ với một bảng không tồn tại!.

Giải pháp: rút mã khóa ngoại ra khỏi 'priorities'bảng. tập tin di chuyển của bạn nên như thế này:

nhập mô tả hình ảnh ở đây

và thêm vào một tệp di chuyển mới, ở đây tên của nó là create_prioritiesForeignKey_tablevà thêm các mã sau:

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

2

hãy chắc chắn rằng cột foraway của bạn vượt qua cơn thịnh nộ của việc bỏ cột chính

Tôi có nghĩa là forawaykey của bạn (trong bảng thứ hai) phải cùng loại với khóa dự đoán của nhà thơ của bạn (trong bảng đầu tiên)

khóa chính con trỏ của bạn phải được thêm phương thức không dấu, hãy để tôi hiển thị:

trên bảng di chuyển đầu tiên của bạn:

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

trên bảng di chuyển THỨ HAI của bạn:

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

VÍ DỤ KHÁC ĐỂ XEM SỰ KHÁC BIỆT

trên bảng di chuyển đầu tiên của bạn:

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

trên bảng di chuyển THỨ HAI của bạn:

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

XEM NHIỀU LOẠI SỐ MYSQL


2

Một điều tôi nhận thấy là nếu các bảng sử dụng công cụ khác với ràng buộc khóa ngoại không hoạt động.

Ví dụ: nếu một bảng sử dụng:

$table->engine = 'InnoDB';

Và những công dụng khác

$table->engine = 'MyISAM';

sẽ tạo ra một lỗi:

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

Bạn có thể khắc phục điều này bằng cách chỉ cần thêm InnoDB vào cuối quá trình tạo bảng của bạn như sau:

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

Trong trường hợp của tôi, tôi đã tham chiếu một cột số nguyên id trên một cột chuỗi user_id . Tôi đã thay đổi:

$table->string('user_id')

đến:

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

Hy vọng nó sẽ giúp được ai đó!


1

Ý chính là phương pháp nước ngoài sử dụng ALTER_TABLEđể biến trường có sẵn thành khóa ngoại. Vì vậy, bạn phải xác định loại bảng trước khi bạn áp dụng khóa ngoại. Tuy nhiên, nó không phải ở một nơi riêng biệtSchema:: cuộc gọi . Bạn có thể thực hiện cả hai trong quá trình tạo, như thế này:

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

Cũng lưu ý rằng loại user_idđược đặt thành không dấu để khớp với khóa ngoại.


1

Bạn có thể trực tiếp truyền tham số boolean trong cột số nguyên nói rằng nó có nên không dấu hay không. Trong laravel 5.4 mã sau đã giải quyết vấn đề của tôi.

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

Ở đây, tham số thứ hai false biểu thị rằng nó không nên tự động tăng và tham số thứ ba đúng biểu thị rằng nó không được ký. Bạn có thể giữ ràng buộc khóa ngoại trong cùng một di chuyển hoặc tách nó. Nó hoạt động trên cả hai.


1

Nếu không có giải pháp nào ở trên hoạt động cho người mới, hãy kiểm tra xem cả hai ID có cùng loại không: cả hai đều integerhoặc cả haibigInteger , ... Bạn có thể có một cái gì đó như thế này:

Bảng chính (ví dụ người dùng)

$table->bigIncrements('id');

Bảng con (ví dụ ưu tiên)

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

Truy vấn này sẽ thất bại vì users.idlà một BIG INTEGERtrong khi priorities.user_idlà một INTEGER.

Truy vấn đúng trong trường hợp này sẽ là như sau:

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

1

Trong trường hợp của tôi, nó không hoạt động cho đến khi tôi chạy lệnh

composer dump-autoload

bằng cách đó bạn có thể để các khóa ngoại bên trong Schema tạo

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

Nó cũng có thể là thứ tự di chuyển sáng tạo của bạn. Nếu trước tiên bạn tạo bảng ưu tiên và sau bảng người dùng thì nó sẽ sai. Bởi vì di chuyển đầu tiên tìm kiếm bảng người dùng. Vì vậy, bạn phải thay đổi thứ tự di chuyển trên

app/database/migrations

danh mục


1

Đối với tôi, cột bảng mà bảng con tôi tham chiếu không được lập chỉ mục.

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

Bỏ qua việc đặt tên khủng khiếp, đó là từ một hệ thống được thiết kế khủng khiếp khác.


1

Một số lần lỗi này có thể đến do chuỗi di chuyển.

Giống như Người dùng và Đơn hàng là hai bảng

Bảng đơn hàng có khóa foriegn của người dùng (Trong quá trình di chuyển nếu bảng Đơn hàng di chuyển trước thì nó sẽ gây ra sự cố do không có người dùng khớp với khóa ngoại)

Giải pháp: Chỉ cần đặt bảng Cập nhật đơn hàng của bạn bên dưới người dùng để cập nhật

Ví dụ: Trong trường hợp của tôi Bảng giáo dục và trường đại học Bảng giáo dục

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

Trong trương đại học

    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

Một điều mà tôi nghĩ là thiếu trong các câu trả lời ở đây, và vui lòng sửa cho tôi nếu tôi sai, nhưng các khóa ngoại cần được lập chỉ mục trên bảng xoay vòng. Ít nhất là trong mysql dường như là trường hợp.

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

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.