क्या कारण है ERROR: संदर्भित तालिका के लिए दी गई कोई अद्वितीय बाधा मिलान कुंजी नहीं है?


154

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

BEGIN;

CREATE TABLE foo (
    name                VARCHAR(256) PRIMARY KEY
);

CREATE TABLE bar(
    pkey        SERIAL PRIMARY KEY,
    foo_fk      VARCHAR(256) NOT NULL REFERENCES foo(name), 
    name        VARCHAR(256) NOT NULL, 
    UNIQUE (foo_fk,name)
);

CREATE TABLE baz(   
    pkey            SERIAL PRIMARY KEY,
    bar_fk          VARCHAR(256) NOT NULL REFERENCES bar(name),
    name            VARCHAR(256)
);

COMMIT;

उपरोक्त कोड चलाने से निम्नलिखित त्रुटि होती है, जो मुझे समझ में नहीं आती है, क्या कोई समझा सकता है कि यह त्रुटि क्यों उत्पन्न होती है। मैं 9.1 पोस्टग्रेज का उपयोग कर रहा हूं

NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
NOTICE:  CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "bar_pkey" for table "bar"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar"
NOTICE:  CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "baz_pkey" for table "baz"
ERROR:  there is no unique constraint matching given keys for referenced table "bar"


********** Error **********

ERROR: there is no unique constraint matching given keys for referenced table "bar"
SQL state: 42830

जवाबों:


188

ऐसा इसलिए है क्योंकि टेबल nameपर मौजूद कॉलम barमें UNIQUE की कमी नहीं है ।

तो कल्पना करें कि आपके पास barतालिका में 2 पंक्तियाँ हैं जिनमें नाम शामिल है 'ams'और आप एक पंक्ति को इसके bazसाथ सम्मिलित 'ams'करते हैं bar_fk, barयह दो पंक्तियों के मिलान के बाद कौन सी पंक्ति होगी?


1
सही लघु और सटीक और स्पष्टीकरण को पकड़ने में आसान!
एलेक्स

79

Postgresql में सभी विदेशी कुंजियों को मूल तालिका में एक अद्वितीय कुंजी का संदर्भ देना चाहिए , इसलिए आपकी barतालिका में आपके पास एक unique (name)इंडेक्स होना चाहिए ।

Http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK और विशेष रूप से देखें :

अंत में, हमें यह उल्लेख करना चाहिए कि एक विदेशी कुंजी में उन कॉलमों का संदर्भ होना चाहिए जो या तो एक प्राथमिक कुंजी हैं या एक अद्वितीय बाधा बनाते हैं।

जोर मेरा।


21
घोषित पीके को एक अद्वितीय बाधा क्यों नहीं माना जाता है? ऐसा नहीं है कि आपके पास एक गैर-पीके हो सकता है ...
उभयचर

2
यह "अंक" की तालिका में अद्वितीय होना चाहिए, क्योंकि यदि यह नहीं है, तो डेटाबेस इंजन को यह जानने का कोई तरीका नहीं होगा कि आप वास्तव में किस पंक्ति का उल्लेख कर रहे हैं।
मट्टियो त्सनेरी

समग्र कुंजी? @amphibient
चार्मिंग रोबोट

1
मुझे लगता है कि माता-पिता की मेज पर संदर्भित स्तंभ पर एक अद्वितीय कुंजी रखने की आवश्यकता केवल पोस्टग्रैक्स्ल में ही नहीं है, बल्कि यह अन्य आरडीबीएमएस जैसे ओरेकल, एसक्यूएल सर्वर आदि भी है
मुफ़ाचिर हुसैन

2
ध्यान दें कि यह उत्तर समग्र विदेशी कुंजियों के लिए भी सही है, जहां मूल तालिका पर एक समग्र अद्वितीय बाधा या प्राथमिक कुंजी आवश्यक है।
निन्जाकन्नन

8

जब आप UNIQUEएक टेबल लेवल अड़चन के रूप में करते हैं जैसा कि आपने किया है, तो आपकी परिभाषा क्या है एक समग्र प्राथमिक कुंजी की तरह देखें ddl बाधाओं को देखें , यहां एक एक्सट्रैक्ट है

"This specifies that the *combination* of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique."

इसका मतलब यह है कि या तो क्षेत्र संभवतः एक गैर अद्वितीय मूल्य हो सकता है बशर्ते संयोजन अद्वितीय है और यह आपके विदेशी कुंजी बाधा से मेल नहीं खाता है।

सबसे अधिक संभावना है कि आप चाहते हैं कि बाधा स्तंभ स्तर पर हो। इसके बजाय तब उन्हें टेबल लेवल की कमी के रूप में परिभाषित करें, UNIQUEकॉलम परिभाषा के अंत में 'परिशिष्ट' की तरह name VARCHAR(60) NOT NULL UNIQUEया प्रत्येक क्षेत्र के लिए इंडिविजुअल टेबल लेवल बाधाओं को निर्दिष्ट करें।


मेरी स्थिति में कॉलम स्तर की बाधा काम नहीं करेगी मुझे वास्तव में एक यौगिक प्राथमिक कुंजी को परिभाषित करना चाहिए, लेकिन मैंने इसे दूर कर दिया क्योंकि जेपीए को इसकी थोड़ी सी भी मैपिंग करना :)
ams

6

आपके पास एक अद्वितीय बाधा के रूप में नाम स्तंभ होना चाहिए। यहां आपके मुद्दों को बदलने के लिए कोड की 3 लाइनें हैं

  1. पहले इस कोड को टाइप करके प्राथमिक कुंजी बाधाओं का पता लगाएं

    \d table_name

    आपको नीचे इस तरह दिखाया गया है "some_constraint" PRIMARY KEY, btree (column)

  2. बाधा छोड़ें:

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
  3. मौजूदा एक के साथ एक नया प्राथमिक कुंजी कॉलम जोड़ें:

    ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);

बस इतना ही।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.