प्रवासन: विदेशी कुंजी बाधा नहीं जोड़ सकते


207

मैं लारवेल में विदेशी कुंजियाँ बनाने की कोशिश कर रहा हूँ, लेकिन जब मैं अपनी तालिका को माइग्रेट करता 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 कॉलम से मेल खाए। लारवेल का वेतन वृद्धि ('आईडी') फ़ंक्शन एक अहस्ताक्षरित पूर्णांक बनाता है, इसलिए विदेशी कुंजी कॉलम को भी अहस्ताक्षरित होना चाहिए।
ब्रैड ग्रिफिथ

7
अलग-अलग जोड़कर, अलग करने से Schema::tableविधि में मदद मिली! धन्यवाद!
patrickjason91

4
मेरे लिए यह आईडी को भी अहस्ताक्षरित नहीं बना रहा था। पारितोषिक के लिए धन्यवाद।
कार्ल वीस

6
इसका समाधान @BradGriffith की टिप्पणी में है। जैसा कि मेरे ऊपर उल्लेख किया गया है कि अलग होने की कोई आवश्यकता नहीं है। हो सकता है कि तदनुसार उत्तर को अपडेट करना बेहतर हो।
मतान्य

11
उपयोग करें $table->unsignedBigInteger('user_id')यदि आपका user.id हैbigIncrements
इवानोव

114

प्रश्न पहले से ही उत्तर दिया गया है, लेकिन आशा है कि यह किसी और की मदद कर सकता है।

यह त्रुटि मेरे लिए हुई क्योंकि मैंने इसमें पहली बार विदेशी कुंजी के साथ माइग्रेशन टेबल बनाई थी, कुंजी के मूल तालिका में प्राथमिक कुंजी के रूप में मौजूद होने से पहले। माइग्रेशन को उस क्रम में निष्पादित किया जाता है जिस क्रम में उन्हें बनाया गया था जैसा कि चलने के बाद उत्पन्न फ़ाइल नाम से संकेत मिलता है migrate:make। जैसे 2014_05_10_165709_create_student_table.php

समाधान को पहले की सिफारिश की गई फ़ाइल की तुलना में विदेशी कुंजी के साथ फ़ाइल को पहले की तरह प्राथमिक कुंजी के साथ बदलना था: http://forumsarchive.laravel.io/viewtopic.php?id=10246

मुझे लगता है कि मुझे भी इसमें शामिल होना था $table->engine = 'InnoDB';


4
आपके द्वारा माइग्रेशन फ़ाइल का नाम बदलने और कुछ त्रुटियां प्राप्त करने के बाद जैसे: स्ट्रीम खोलने में विफल: ऐसी कोई फ़ाइल या निर्देशिका (और पुराना माइग्रेशन नाम प्रदर्शित नहीं होता) आपको चलाना होगा: संगीतकार डंप-
ऑटोलॉड

14
$ तालिका-> इंजन = 'InnoDB'; MySql स्तर पर विदेशी कुंजी लागू करने के लिए आवश्यक है। डिफ़ॉल्ट लार्वा इंजन MyIsam है जो विदेशी कुंजियों का समर्थन नहीं करता है!
फ्रांस्वा ब्रेटन

2
यह मेरे लिए भी काम किया, धन्यवाद। लेकिन यह मुझे थोड़ा अजीब लगता है कि यह इस तरह से काम करता है। मेरा मतलब है, यह समझ में आता है, लेकिन मैन्युअल रूप से निष्पादन के आदेश को निर्दिष्ट करने का एक तरीका होना चाहिए, मैन्युअल रूप से फ़ाइलों का नाम बदलने और इस प्रक्रिया में नकली तिथियों के साथ आने के अलावा
15

2
मैं यहां इसलिए नहीं आया क्योंकि मुझे कोई त्रुटि मिल रही थी, लेकिन मैं उस कॉलम में गलत मान जोड़ने में सक्षम था जो एक विदेशी कुंजी थी। फिर मैंने InnoDB के बारे में टिप्पणी और उत्तर देखा। यह जानकर अच्छा लगा। धन्यवाद दोस्तों :)
SuperNOVA

2
जिस क्रम में आपने अपना माइग्रेशन बनाया है वह तब भी माइग्रेट करते समय महत्वपूर्ण रहता है। मैं इस मुद्दे पर भाग गया लेकिन इसने इसे हल कर दिया।
मगबिट्स

60

लारवेल ^ 5.8

Laravel 5.8 के अनुसार , माइग्रेशन स्टब्स डिफ़ॉल्ट रूप से ID कॉलम पर bigIncrements विधि का उपयोग करते हैं। पहले, वेतन वृद्धि विधि का उपयोग करके आईडी कॉलम बनाए गए थे।

यह आपकी परियोजना में किसी भी मौजूदा कोड को प्रभावित नहीं करेगा; हालाँकि, इस बात का ध्यान रखें कि विदेशी कुंजी कॉलम एक ही प्रकार के होने चाहिए । इसलिए, वेतन वृद्धि विधि का उपयोग करके बनाया गया स्तंभ bigIncrements विधि का उपयोग करके बनाए गए स्तंभ का संदर्भ नहीं दे सकता है

स्रोत: माइग्रेशन और बिग इंक्रीमेंट


उदाहरण

आइए कल्पना करें कि आप एक साधारण भूमिका-आधारित अनुप्रयोग का निर्माण कर रहे हैं, और आपको PIVOT तालिका "role_user" में user_id का संदर्भ देना होगा

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 है ) role_user तालिका में bigInteger या उपयोगकर्ताओं की तालिका में वेतन वृद्धि विधि में bigIncrements विधि बदलें और पिवट तालिका में टिप्पणी की गई पंक्ति का उपयोग करें, यह आपके ऊपर है।


मुझे आशा है कि मैं आपको इस मुद्दे को स्पष्ट करने में सक्षम था।


1
धन्यवाद। तुमने मेरी जान बचाई। आपके स्पष्टीकरण के बाद, मैंने अपनी विदेशी कुंजी को बड़े Integer में बदल दिया, जैसे आपने सुझाव दिया था। 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
@ ब्रूसटोंग, मुझे खुशी है कि मैं मदद करने में सक्षम था।
chebaby

1
हाँ यह सबसे प्रासंगिक जवाब है।
मोहम्मद अब्दुल मुजीब

1
यह उत्तर बहुत मददगार है।
करीम पज़ोकी

1
सबसे बढ़िया उत्तर। धन्यवाद
VishalParkash

49

मेरे मामले में, मुद्दा यह था कि मुख्य तालिका में पहले से ही रिकॉर्ड था और मैं नया कॉलम NULL नहीं होने के लिए मजबूर कर रहा था। इसलिए नए कॉलम में a -> nullable () को जोड़कर चाल चली। प्रश्न के उदाहरण में कुछ इस तरह होगा:

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

या:

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

आशा है कि यह किसी की मदद करता है!


ध्यान दें कि आपकी मूल तालिका में 'आईडी' कॉलम को भी अहस्ताक्षरित होना चाहिए! $ तालिका-> वेतन वृद्धि ('आईडी') जैसी लाइन का उपयोग करना; अहस्ताक्षरित करने के लिए स्वचालित रूप से डिफ़ॉल्ट होगा।
कॉलिन स्टैडिग सिप

इसने मेरे लिए काम किया। मैंने BigIncrements से वेतन वृद्धि के लिए मूल तालिका आईडी का डेटा प्रकार बदल दिया।
इमैनुएल बेन्सन

22

मेरे मामले में समस्या यह थी कि usersतालिका के लिए ऑटो-जनरेट माइग्रेशन सेटिंग कर रहा था

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

इसलिए मुझे कॉलम का प्रकार बदलना पड़ा


$table->bigInteger('id');

विदेशी प्रमुख काम के साथ मेरा प्रवासन करने के लिए।

यह लार्वा के साथ 5.8.2


क्योंकि विदेशी कुंजी कॉलम में उसी प्रकार का कॉलम होना चाहिए जो इसे संदर्भित करता है
Daniele

9
इसने मेरे लिए $ तालिका-> अहस्ताक्षरित Integer ('user_id') काम किया;
लारवेल में

मैं भी 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 कारीगर को स्थानांतरित करते हैं । यह एक अपवाद को फेंक देगा क्योंकि माइग्रेशन पहले आपके डेटाबेस में बेस टेबल बनाएगा क्योंकि आपने यह माइग्रेशन पहले बनाया है और हमारी बेस टेबल में विदेशी कुंजी अवरोध है जो चाइल्ड टेबल की तलाश करेगा और चाइल्ड टेबल मौजूद नहीं है जो संभवतः है एक अपवाद..

इसलिए:

पहले चाइल्ड टेबल माइग्रेशन बनाएं।

चाइल्ड माइग्रेशन बनने के बाद बेस टेबल माइग्रेशन बनाएं।

php कारीगर पलायन करते हैं।

यह काम करेगा


13

मेरे मामले में मैं सिर्फ ऑर्डर बदल देता हूं माइग्रेशन मैन्युअल रूप से निष्पादित किए जाते हैं इसलिए तालिका उपयोगकर्ता पहले बनाए जाते हैं।

फ़ोल्डर डेटाबेस / माइग्रेशन / आपके माइग्रेशन फ़ाइलनाम में यह प्रारूप होता है: वर्ष_मूर्ति_दिन_हम्म्स_क्रिएट_एक्सएक्सएक्सएक्सएक्स_टेबल। एफपीपी

बस उपयोगकर्ता नाम बनाएं ताकि आपकी तालिका प्राथमिकताओं की तालिका का निर्माण दिनांक उपयोगकर्ता तिथि से बाद में सेट हो (एक सेकंड बाद में भी पर्याप्त है)


13

लार्वा 5.8 में, उपयोगकर्ता_उपयोगकर्ता bigIncrements('id')प्राथमिक कुंजी के लिए डेटा प्रकार का उपयोग करता है । ताकि जब आप किसी विदेशी कुंजी को संदर्भित करना चाहें तो आपके user_idकॉलम को unsignedBigInteger('user_id')टाइप करना पड़े।


बहुत-बहुत धन्यवाद, मैंने यह जानने में एक घंटा बिताया कि विदेशी कुंजी अपवाद का कारण क्यों है
Ya Basha

10

मैं Laravel 5.8 का उपयोग कर एक ही मुद्दा रहा था लार्वा डॉक्स पर करीब से नज़र डालने के बाद, यहाँ पर माइग्रेशन और बिग इन्क्रिमेंट्स हैं । जिस तरह से मैंने इसे हल किया है वह प्राथमिक कुंजियों "$ तालिका-> bigIncrements ('id')" को हर एक तालिका से जोड़कर है जो तालिका "उपयोगकर्ता" और उसके संघों से संबंधित है, मेरे मामले में तालिका "भूमिका" । अंत में, मेरे पास उपयोगकर्ताओं (कई-से-कई), यानी, टेबल "role_user" में भूमिकाओं को जोड़ने के लिए "$ table-> अहस्ताक्षरित " था

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

मेरे पास लार्वा 5.8 के साथ यह मुद्दा था और मैंने इस कोड को तय किया, जैसा कि लारवेल प्रलेखन में यहां दिखाया गया है , जहां कभी भी मैं एक विदेशी कुंजी जोड़ रहा हूं।

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

फिर मैं भागा $ php artisan migrate:refresh

चूंकि यह वाक्यविन्यास बल्कि क्रिया है, इसलिए लारवेल अतिरिक्त, टसर तरीके प्रदान करता है जो एक बेहतर डेवलपर अनुभव प्रदान करने के लिए सम्मेलन का उपयोग करते हैं। ऊपर का उदाहरण इस तरह लिखा जा सकता है:

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

7

लारवेल 5.3 का उपयोग करने में भी यही समस्या थी।

समाधान पूर्णांक ('नाम') -> अहस्ताक्षरित () के बजाय अहस्ताक्षरित का उपयोग करना था ।

तो यह है कि क्या काम किया है

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

यह काम करने का कारण यह है कि पूर्णांक ('नाम') का उपयोग करते समय -> अहस्ताक्षरित तालिका में बनाए गए कॉलम की लंबाई 11 थी, लेकिन जब unsigedInteger ('नाम') का उपयोग करते हुए स्तंभ की लंबाई 10 थी।

लंबाई 10 प्राथमिक कुंजियों की लंबाई है जब लारवेल का उपयोग किया जाता है ताकि कॉलम की लंबाई मेल खाए।


यार, इसके लिए मैं आपको धन्यवाद देता हूं कि मैं आपका पद पाने के बाद कच्चा चिट्ठा छोड़ने वाला था। मुझे इस बारे में अधिक पढ़ना होगा कि लार्वावेल प्राथमिक कुंजी को 10 की लंबाई के लिए क्यों मजबूर किया जाता है और यदि कोई कारण है कि पूर्णांक ('कॉलम') -> अहस्ताक्षरित () unsigedInteger ('कॉलम') से अलग होना चाहिए
अरनौद बाउचोट

6

मेरे लिए यह त्रुटि इसलिए आई क्योंकि - मैं जिस तालिका को बनाने का प्रयास कर रहा था, वह InnoDB थी - जिस विदेशी तालिका से मैं संबंधित था, वह एक MyISAM तालिका थी!


MyISAM विदेशी प्रमुख बाधाओं का समर्थन नहीं करता है। इसने काम किया क्योंकि MyISAM पर स्विच करने के कारण यह विदेशी कुंजी को पूरी तरह से अनदेखा कर देता था जो संभवतः एक कारण के लिए था। सावधान रहे।
greggle138

5

हम संबंध तब तक नहीं जोड़ सकते, जब तक संबंधित तालिकाएँ नहीं बन जातीं। 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');
    });

1
आपने फाइल का नाम क्या रखा है? 9999_99_99_999999_create_foreign_keys.php?
इनाज़ज़ी

माइग्रेशन फ़ाइलनाम में 9999_99_99_99999 जोड़ना बुरा विचार है क्योंकि यह रोलबैक सुविधा को बढ़ा देगा।
मौलिक गंगानी

5

ध्यान रखें: जब लारवेल का उपयोग करके एक टेबल सेट की जाती है

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

विदेशी कुंजी क्षेत्र अहस्ताक्षरित होना चाहिए , आशा है कि यह मदद करता है !!


न केवल अहस्ताक्षरित, लेकिन जब यह एक बड़ेIncrements कॉलम का संदर्भ देता है, तो इसे unsigedBigInteger होना चाहिए
गोंडवे

4

लार्वा में विदेशी कुंजी बाधा बनाने के लिए, निम्नलिखित ने मेरे लिए काम किया:

  1. स्तंभ को विदेशी कुंजी के रूप में बनाएँ:

    $ टेबल> पूर्णांक ( 'COLUMN_NAME') -> अहस्ताक्षरित ();
  2. (1) के तुरंत बाद बाधा लाइन जोड़ना

    $ टेबल> पूर्णांक ( 'COLUMN_NAME') -> अहस्ताक्षरित ();
    $ टेबल> विदेशी ( 'COLUMN_NAME') -> संदर्भ ( 'pk_of_other_table') -> पर ( 'other_table');

3

मुझे पता है कि एक पुराना सवाल है, लेकिन सुनिश्चित करें कि आप संदर्भों के साथ काम कर रहे हैं तो उचित सहायक इंजन परिभाषित है। दोनों स्तंभों के लिए निर्दोष इंजन सेट करें और संदर्भ कॉलम के लिए समान डेटा प्रकार

$table->engine = 'InnoDB';

2

मूल प्रश्न के कुछ साल बाद यहाँ लार्वा ५.१ का उपयोग करते हुए, मेरे पास एक ही त्रुटि थी क्योंकि मेरे माइग्रेशन कंप्यूटर सभी समान दिनांक कोड के साथ उत्पन्न हुए थे। मैं सभी प्रस्तावित समाधानों से गुजरा, फिर त्रुटि स्रोत को खोजने के लिए फिर से तैयार किया।

निम्नलिखित लार्कास्ट में, और इन पदों को पढ़ने में, मेरा मानना ​​है कि सही उत्तर विक्की के जवाब के समान है, इस अपवाद के साथ कि आपको एक अलग स्कीमा कॉल जोड़ने की आवश्यकता नहीं है। आपको इनोडब को तालिका सेट करने की आवश्यकता नहीं है, मुझे लगता है कि लार्वा अब ऐसा कर रहा है।

माइग्रेशन को बस सही तरीके से समयबद्ध करने की आवश्यकता है, जिसका अर्थ है कि आप उन तालिकाओं के लिए फ़ाइल नाम में दिनांक कोड को (बाद में) संशोधित करेंगे जिन्हें आपको विदेशी कुंजी की आवश्यकता है। वैकल्पिक रूप से या इसके अलावा, उन तालिकाओं के लिए डेटकोड कम करें जिनकी विदेशी कुंजी की आवश्यकता नहीं है।

डेटकोड को संशोधित करने में लाभ यह है कि आपका माइग्रेशन कोड पढ़ने और बनाए रखने में आसान होगा।

अब तक मेरा कोड विदेशी कुंजी की आवश्यकता वाले माइग्रेशन को पीछे धकेलने के लिए समय कोड को समायोजित करके काम कर रहा है।

हालाँकि, मेरे पास सैकड़ों टेबल हैं, इसलिए बहुत अंत में मेरे पास सिर्फ विदेशी चाबियों के लिए एक आखिरी टेबल है। बस चीजों को पाने के लिए। मैं मान रहा हूं कि मैं उन लोगों को सही फ़ाइल में खींच लूंगा और जैसे ही मैं उनका परीक्षण करूंगा, डेटकोड को संशोधित कर दूंगा।

तो एक उदाहरण: फ़ाइल 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

सुनिश्चित करें कि आपका अग्रगामी स्तंभ विस्तृत कुंजी स्तंभ के क्रोध पर है

मेरा मतलब है कि आपका अग्रभाग (दूसरी तालिका में) आपके पॉंटर प्रिकिपल कुंजी का एक ही प्रकार होना चाहिए (पहली तालिका में)

आपके पॉइंटर प्रिंसिपल कुंजी को अहस्ताक्षरित विधि जोड़ना होगा, मुझे दिखाने दें:

अपनी FIRST माइग्रेशन टेबल पर:

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

आपके सेकंड माइग्रेशन टेबल पर:

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

विभिन्न उदाहरण देखें

अपनी FIRST माइग्रेशन टेबल पर:

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

आपके सेकंड माइग्रेशन टेबल पर:

$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

आप अपनी तालिका निर्माण के अंत में सिर्फ इनोबीडी जोड़कर इसे ठीक कर सकते हैं:

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

आप सीधे पूर्णांक कॉलम में बूलियन पैरामीटर को यह कहते हुए पारित कर सकते हैं कि यह अहस्ताक्षरित होना चाहिए या नहीं। लारवल 5.4 में निम्नलिखित कोड ने मेरी समस्या हल कर दी।

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

यहाँ दूसरा पैरामीटर झूठी का प्रतिनिधित्व करता है कि यह ऑटो बढ़ाने और तीसरे पैरामीटर नहीं होना चाहिए सच का प्रतिनिधित्व करता है कि यह अहस्ताक्षरित किया जाना चाहिए। आप विदेशी मुख्य बाधा को एक ही प्रवास में रख सकते हैं या इसे अलग कर सकते हैं। यह दोनों पर काम करता है।


1

यदि newbies के लिए काम से ऊपर दिए गए समाधानों में से कोई भी जाँच नहीं करता है यदि दोनों आईडी में एक ही प्रकार है: दोनों हैं 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

इस तरह से आप Create स्कीमा के अंदर विदेशी कुंजी छोड़ सकते हैं

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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.