2012-08-28 18 views
6

में एक-से-कई लोगों के लिए एक बहुत-से-अनेक संबंध परिवर्तित मैं एक बहुत-से-अनेक foo और bar के बीच foo_id और bar_id के साथ एक मेज foo_bar के रूप में मॉडलिंग की है।PostgreSQL

अब मैं इसे एक से कई के रूप में मॉडल करना चाहता हूं (जो मेरा डेटा अनुमति देता है)।

मैंने foo_id कॉलम को bar पर जोड़ा है लेकिन अब मैं अपना डेटा माइग्रेट करना चाहता हूं। तो, मैं जहां प्रत्येक f और b जोड़ी से

SELECT foo_id AS f, bar_id AS b FROM foo_bar; 

आ रहे हैं

UPDATE bar SET foo_id = f where id = b; 

करना चाहते हैं यह एसक्यूएल (और विशेष रूप से PostgreSQL 9.0) में ऐसा करना संभव है?

मुझे पता है कि अद्यतन में उप-चयन कैसे करें जब केवल एक मान हो, लेकिन इस मामले में इसे कैसे किया जाए।

उत्तर

5
UPDATE bar b 
SET foo_id = fb.foo_id 
FROM foo_bar fb 
WHERE fb.bar_id = b.bar_id; 

आप एक bar के लिए कई पंक्तियां (आप नहीं, अपने विवरण के अनुसार चाहिए) एक पंक्ति में कई बार अपडेट किया जाएगा होनी चाहिए और परिणाम मनमाना है।

क्वेरी का यह रूप आमतौर पर एक सहसंबंधित सबक्वायरी से बेहतर प्रदर्शन करता है।

ध्यान दें कि bar की प्राथमिक कुंजी को वास्तव में bar_id नाम दिया जाना चाहिए - मैं क्वेरी में उस नाम का उपयोग करता हूं।

+0

लाइन पिछले हो fb.bar_id = b.id चाहिए? –

+0

@ जेम्स टाउबर: नहीं। मॉडल में 'आईडी' नहीं होना चाहिए। गैर-वर्णनात्मक कॉलम नाम 'आईडी' का प्रयोग एक विरोधी पैटर्न है। प्राथमिक कुंजी को 'bar_id' नाम दिया जाना चाहिए। –

+0

काफी उचित है, बस मेरे प्रश्न –

2

यदि आपके पास वास्तव में 1-बहुत से रिश्ते हैं, तो इससे कोई फ़र्क नहीं पड़ता कि आप किसी दिए गए बार के लिए कितने foo लेते हैं - केवल एक ही है या वे सभी समान हैं।

आप निम्न कर सकते हैं:

update bar 
    set foo_id = (select max(foo_id) from foo_bar where foo_bar.bar_id = bar.id) 

सबक्वेरी किसी एकल मान के लिए परिणामों को सीमित करता।

3

तुम अब भी UPDATE बयान में तालिकाओं शामिल हो सकते हैं, कोशिश

UPDATE bar a 
SET  foo_id = c.foo_id 
FROM (
      SELECT foo_id, bar_id 
      FROM foo_bar 
     ) c 
WHERE a.id = c.bar_id 

या बस के रूप में

UPDATE bar a 
SET  foo_id = c.foo_id 
FROM foo_bar c 
WHERE a.id = c.bar_id 
+0

'SET' के विनिर्देशों के लिए मैपिंग कर रहा था तालिका-योग्य कॉलम नाम स्वीकार नहीं करता है। –

+0

@ErwinBrandstetter वास्तव में इसका परीक्षण नहीं किया जाता है। क्या पोस्टग्रे पर्याप्त सख्त है? हे, इसलिए इस मामले में मुझे इसे 'SET foo_id = c.foo_id'' पर फिर से लिखना चाहिए? –

+0

बिल्कुल सही: 'SET foo_id = c.foo_id', मेरे उत्तर में। मैं मैनुअल उद्धृत करता हूं [http] // www.postgresql.org/docs/current/interactive/sql-update.html): 'लक्ष्य कॉलम के विनिर्देशन में तालिका का नाम शामिल न करें - उदाहरण के लिए, अद्यतन टैब सेट टैब.col = 1 अमान्य है। –