2012-09-14 28 views
8

के दौरान किसी अन्य कॉलम में सीरियल कॉलम का संदर्भ मान मेरे पास एक सीरियल प्राथमिक कुंजी के साथ एक तालिका है, और एक लेटी कॉलम भी है, जिसका मूल्य मैं उन प्राथमिक कुंजी का संगत होना चाहता हूं। जैसेउसी INSERT

id | path 
---------- 
1 1 
2 1.2 
3 1.2.3 
4 1.4 
5 1.5 

यदि मैं एक प्रश्न में ऐसा सम्मिलित करने का कोई तरीका है, तो मैं उत्सुक हूं, उदा।

INSERT INTO foo (id, ltree) VALUES (DEFAULT, THIS.id::text) 
मैं शायद यहाँ overreaching कर रहा हूँ और एक क्वेरी में करने के लिए मैं क्या दो (लेन-देन में वर्गीकृत किया) में करना चाहिए की कोशिश कर रहा

+0

वह पथ बहुत संदिग्ध नहीं दिखता है .. –

+0

मेरे पथ मान इस पर आधारित हैं: http://stackoverflow.com/a/607379/39529 –

+0

PostgreSQL में रिकर्सन, सामान्य तालिका अभिव्यक्ति, बहुत आसान और तेज़ है आपका पथ समाधान/कामकाज। –

उत्तर

7

आप एक बार अनुक्रम से मान प्राप्त करने के लिए एक सबक्वेरी या एक लिखने योग्य CTE उपयोग करें और यह बार-बार इस्तेमाल कर सकते हैं:

मैं व्यक्तिगत रूप से इस (छद्म कोड) करने के लिए इच्छुक हो जाएगा
WITH i AS (
    SELECT nextval('foo_id_seq') AS id 
    ) 
INSERT INTO foo (id, ltree) 
SELECT id, '1.' || id 
FROM i; 

Data-modifying CTE को पोस्टग्रेज़ 9.1 या बाद की आवश्यकता है।

आप के बजाय pg_get_serial_sequence() उपयोग कर सकते हैं आप अनुक्रम के नाम के बारे में निश्चित नहीं हैं:

WITH i AS (
    SELECT nextval(pg_get_serial_sequence('foo', 'id')) AS id 
    ) 
INSERT INTO foo (id, ltree) 
SELECT id, '1.' || id 
FROM i; 

तालिका नाम "foo" DB में सभी स्कीमा भर में अद्वितीय नहीं हो सकता है, तो आप कर सकते हैं स्कीमा इसे योग्य बनाएं।

INSERT INTO foo (ltree) VALUES ('1.' || lastval()); 
:

pg_get_serial_sequence('"My_odd_Schema".foo', 'id') 



त्वरित परीक्षण के साथ भी lastval()सकता है काम @Mark's idea संकेत दिया: और अगर किसी भी नाम की वर्तनी गैर मानक है, तो आप इस बात की दोबारा बोली के लिए है

  • आप क्वेरी से बाहर id छोड़ सकते हैं, serial कॉलम स्वचालित रूप से असाइन किया जाएगा। कोई फर्क नहीं पड़ता।

  • पंक्तियों के बीच दौड़ की स्थिति नहीं होनी चाहिए। मैं quote the manual:

currval

Return the value most recently obtained by nextval for this sequence in the current session. (An error is reported if nextval has never been called for this sequence in this session.) Because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did.

lastval

Return the value most recently returned by nextval in the current session. This function is identical to currval, except that instead of taking the sequence name as an argument it fetches the value of the last sequence used by nextval in the current session. It is an error to call lastval if nextval has not yet been called in the current session.

बोल्ड जोर मेरा।

लेकिन, @Bernard commented के रूप में, यह सब के बाद असफल हो सकता है।दूसरे विचार पर, यह समझ में आता है: इस बात की कोई गारंटी नहीं है कि डिफ़ॉल्ट मान भरा हुआ है (और nextval() प्रक्रिया में बुलाया गया है) lastval() को दूसरे कॉलम ltree भरने के लिए बुलाया जाता है। तो सुनिश्चित करने के लिए पहले समाधान और nextval() के साथ चिपके रहें।

+0

बिल्कुल वही जो मैं खोज रहा था, धन्यवाद! –

+0

क्या यह गारंटी है कि अगली प्राथमिक कुंजी खोजने के लिए 'अगलीवाल() 'पहले कॉल किया जाएगा, ताकि' lastval()' कोई त्रुटि नहीं फेंक सके? – Bernard

+1

आपका दूसरा सुझाव '55000 त्रुटि को फेंकता है: पोस्टग्रेएसक्यूएल 9.5 पर आखिरी बार इस सत्र में परिभाषित नहीं किया गया है। – Bernard

3

यह मेरा परीक्षण में काम किया:

INSERT INTO foo (id, ltree) VALUES (DEFAULT, (SELECT last_value from foo_id_seq)); 

मुझे लगता है कि वहाँ एक रेस स्थिति वहाँ अगर दो आवेषण एक ही समय में हो रही हैं है, इस संदर्भ देता है के बाद से पिछले अनुक्रम मूल्य, वर्तमान पंक्ति के बजाय।

my $id = SELECT nextval('foo_id_seq'); 
INSERT INTO foo (id, ltree) VALUES ($id, '$id');