किसी विदेशी कुंजी बाधा वाले स्तंभ को पहले से मौजूद तालिका में कैसे जोड़ा जाए?


11

मेरे पास निम्न तालिकाएँ हैं,

CREATE TABLE users (id int PRIMARY KEY);

-- already exists with data
CREATE TABLE message ();

मैं messagesतालिका को कैसे बदलूं ,

  1. इसमें एक नया कॉलम senderजोड़ा गया है
  2. तालिका का senderसंदर्भ देने वाली एक विदेशी कुंजी कहां हैusers

यह काम नहीं किया

# ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
ERROR:  column "sender" referenced in foreign key constraint does not exist

क्या यह कथन कॉलम भी नहीं बनाता है?


3
आपको संदर्भ देने से पहले कॉलम बनाना होगा। मैं यहां पर ALTER TABLE के लिए प्रलेखन पढ़ने की भी कोशिश करूंगा , और उदाहरणों पर बहुत ध्यान दूंगा।
कसंड्री

हासन, मैंने डीडीएल का उपयोग करने के लिए इस सवाल को साफ किया और मैंने उन चीजों को हटा दिया जो काम नहीं कर रही थीं। देखें कि क्या यह सवाल का जवाब देता है: dba.stackexchange.com/a/202564/2639 । इन संपादनों में से किसी को भी अस्वीकार करने के लिए स्वतंत्र महसूस करें, मैं सिर्फ इसे पोस्टीरिटी के लिए साफ करना चाहता था।
इवान कैरोल

जवाबों:


18

क्या अपेक्षाकृत आसान है - आपको बस एक और कदम जोड़ना होगा।

FOREIGN KEYस्तंभ का अस्तित्व है ताकि इसे एक बनाने के लिए FK। मैंने निम्नलिखित ( यहाँ और प्रलेखन से ) किया:

CREATE TABLE x(t INT PRIMARY KEY);

CREATE TABLE y(s INT);

ALTER TABLE y ADD COLUMN z INT;    

ALTER TABLE y
  ADD CONSTRAINT y_x_fkey FOREIGN KEY (z)
      REFERENCES x (t)
      ON UPDATE CASCADE ON DELETE CASCADE;

नोट करने के लिए कुछ बिंदु:

हमेशा अपने विदेशी कुंजी सार्थक नाम दे। बताया जा रहा है कि कुंजी "SYS_C00308108" का उल्लंघन किया जा रहा है, बहुत उपयोगी नहीं है। बेला देखें यहाँ इन परिस्थितियों कुंजी नाम बेला को बेला से अलग अलग होंगे तहत ओरेकल के व्यवहार के लिए, लेकिन कुछ मनमाने ढंग से स्ट्रिंग _... SYS के साथ शुरुआत) है

आपके कथन को ध्यान में रखते हुए:

ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;

यह "अच्छा-से-होगा" होगा यदि RDBMS स्वचालित रूप से उस फ़ील्ड को बना सकता है जिसे आप संदर्भित फ़ील्ड से मेल खाते डेटा प्रकार के साथ चाहते हैं। मैं बस इतना ही कहूंगा कि डीडीएल को बदलना (या कम से कम होना चाहिए) शायद ही कभी इस्तेमाल किया जाने वाला ऑपरेशन है और ऐसा कुछ नहीं जो आप नियमित रूप से करना चाहते हैं। यह पहले से ही पर्याप्त दस्तावेज को जोड़ने का भी जोखिम रखता है।

कम से कम PostgreSQL कुछ उचित करने की कोशिश करता है - यह तालिका का नाम, FOREIGN KEYक्षेत्र का नाम _fkeyऔर यहां तक DETAIL: Key (sender_id)=(56) is not present in table "user_".कि कुछ देने के लिए जोड़ता है जो एक इंसान को समझ में आ सकता है - यहां देखें ।


2
मैं कभी भी अपनी विदेशी चाबियों का नाम नहीं देता। उनका स्वतः नाम मिलता है, और वे आमतौर पर बहुत उपयोगी होते हैं। उदाहरण के लिए, उस संदर्भ में डिफ़ॉल्ट नाम है "y_z_fkey"। मेरा तर्क है कि इससे बेहतर नाम है y_x_fkeyक्योंकि आपका उल्लंघन आपको उस कॉलम को नहीं बताता है जिसे आप त्रुटि के कारण डाल रहे हैं । मुझे इसकी परवाह है कि यह कहाँ इंगित कर रहा है। एक सामान्य नियम के रूप में, आपको अपने fkeys को कभी भी नाम नहीं देना चाहिए और PostgreSQL के डिफ़ॉल्ट को संभालना चाहिए।
इवान कैरोल

इसके अलावा, आप ON UPDATE CASCADE ON DELETE CASCADE;उदाहरण के लिए, विशेष रूप से बिना कारण के चूक को ओवरराइड नहीं करना चाह सकते हैं । यह उदाहरण को और अधिक जटिल बनाता है, और आप यह समझाने की जहमत नहीं उठाते कि यह क्या है। मैं एक के लिए सामान्य रूप से कैस्केड को हटाना नहीं चाहता।
इवान कैरोल

1
कंपनी / परियोजना ने जो निर्णय लिया है, मैं हमेशा एफके का नाम लेता हूं । यह ज्यादा बात करता है, तो यह है नहीं है y_x_fkeyया y_z_fkeyया x__y_FK, जब तक कि यह संगत है के रूप में।
ypercube y

यदि आप अनुबंध कर रहे हैं तो मैं इस बात से बहुत सहमत हूँ - एक कन्वेंशन चुनें और उससे चिपके रहें और / या सुनिश्चित करें कि आप उस कन्वेंशन (एस) के अनुरूप हैं जो पहले सिस्टम के साथ उपयोग किया गया था।
वेरेस

@EvanCarroll - यदि PostgreSQL का कन्वेंशन प्रोजेक्ट का है या पहले सिस्टम पर निर्णय लिया गया है जो शायद PostgreSQL नहीं है - एक सिस्टम अच्छी तरह से शुरू हो सकता है, कह सकते हैं, Oracle या अन्य सिस्टम जिसमें PostgreSQL का कन्वेंशन (s) नहीं हो सकता है। आप तर्क दे सकते हैं कि x_y_z_fk त्रुटि की स्थिति में अधिकतम संभव जानकारी दे सकता है! कुछ उठाओ और उससे चिपके रहना मेरा मकसद है, लेकिन एक आरडीबीएमएस (चाहे कितना भी अच्छा हो) तुम्हारे लिए कन्वेंशन तय मत करो!
वेरेस

8

मुझे यकीन नहीं है कि हर कोई आपको क्यों बता रहा है कि आपको दो चरणों में ऐसा करना होगा। वास्तव में, तुम नहीं । आपने यह मानने की कोशिश की है FOREIGN KEYकि डिजाइन के आधार पर, कॉलम वहां है और यदि स्तंभ नहीं है तो उस त्रुटि को फेंक देता है। यदि आप इसे जोड़ते हैं COLUMN, तो आप इसे स्पष्ट रूप से FOREIGN KEYनिर्माण पर बना सकते हैं REFERENCES,

ALTER TABLE message
  ADD COLUMN sender INT
  REFERENCES users;  -- or REFERENCES table(unique_column)

ठीक काम करेंगे। आप यहाँ का सिंटैक्स देख सकते हैं ALTER TABLE,

ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
action [, ... ]

साथ "कार्रवाई" के रूप में,

ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]

ये उदाहरण डॉक्स में भी हैं,

ALTER TABLE distributors
  ADD CONSTRAINT distfk
  FOREIGN KEY (address)
  REFERENCES addresses (address);

ALTER TABLE distributors
  ADD CONSTRAINT distfk
  FOREIGN KEY (address)
  REFERENCES addresses (address)
  NOT VALID;

लेकिन यह सब आवश्यक नहीं है क्योंकि हम ऑटोनोमिंग और प्राथमिक-कुंजी रिज़ॉल्यूशन पर भरोसा कर सकते हैं (यदि केवल तालिका-नाम निर्दिष्ट किया गया है तो आप प्राथमिक कुंजी को संदर्भित कर रहे हैं)।


0

CASE1: यदि आपको एक नई तालिका बनाते समय विदेशी कुंजी बनाने की आवश्यकता है

CREATE TABLE table1(
id SERIAL PRIMARY KEY,
column1 varchar(n) NOT NULL,
table2_id SMALLINT REFERENCES table2(id)
); 

उपर्युक्त आदेश 'तालिका 1' नाम से एक तालिका बनाएंगे और तीन कॉलम 'आईडी' (प्राथमिक कुंजी), 'कॉलम 1', 'टेबल 2_आईडी' (टेबल की विदेशी कुंजी जो टेबल 2 के आईडी कॉलम को संदर्भित करते हैं) नाम से बनाएंगे।

DATATYPE 'सीरियल' इस डेटाटाइप का उपयोग एक ऑटो-जनरेट किए गए कॉलम के रूप में करेगा, जब तालिका में मान सम्मिलित करने की आवश्यकता होती है, तो आपको इस कॉलम का उल्लेख नहीं करना चाहिए, या आप मूल्य स्थान पर उद्धरण के बिना 'डिफ़ॉल्ट' दे सकते हैं।

एक प्राथमिक कुंजी कॉलम हमेशा 'tablename_pkey' मान के साथ तालिका के सूचकांक में जोड़ा जाता है।

यदि तालिका निर्माण के समय में विदेशी कुंजी जोड़ी जाती है, तो पैटर्न के साथ A CONSTRAINT जोड़ा जाता है '(present_table_name) _ (Foreign_key_id_name) _fkey'।

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

मामले 2: यदि आप मौजूदा कॉलम पर मौजूदा तालिका में विदेशी कुंजी चाहते हैं

ALTER TABLE table1
ADD CONSTRAINT table1_table2_id_id_fkey
FOREIGN KEY (table2_id) REFERENCES table2(id);

नोट: कोष्ठक '()' के बाद कुंजी चिह्न और संदर्भ टैबेल 2 अनिवार्य हैं अन्यथा पोस्टग्रेज त्रुटि को फेंक देंगे।


0

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


1
ओपी ने पूछा: क्या यह कथन कॉलम भी नहीं बनाता है? इसलिए यह स्पष्ट है कि उसे उम्मीद थी कि ऐसा होगा।
लॉरेंज एल्बे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.