( tl;dr
:गोटो विकल्प 3:INSERT with RETURNING )
याद रखें कि postgresql में तालिकाओं के लिए कोई "id" अवधारणा नहीं है, बस अनुक्रम (जो आम तौर पर हैं लेकिन जरूरी नहीं कि सरोगेट प्राथमिक कुंजी के लिए डिफ़ॉल्ट मानों के रूप में उपयोग किया जाता है, सीरियल छद्म-प्रकार के साथ)।
यदि आप नई डाली गई पंक्ति की आईडी प्राप्त करने में रुचि रखते हैं, तो कई तरीके हैं:
विकल्प 1:CURRVAL(<sequence name>);
.
उदाहरण के लिए:
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval('persons_id_seq');
अनुक्रम का नाम ज्ञात होना चाहिए, यह वास्तव में मनमाना है; इस उदाहरण में हम मानते हैं कि तालिका persons
एक id
है SERIAL
. के साथ बनाया गया कॉलम छद्म प्रकार। इस पर भरोसा करने से बचने और अधिक स्वच्छ महसूस करने के लिए, आप इसके बजाय pg_get_serial_sequence
का उपयोग कर सकते हैं :
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
SELECT currval(pg_get_serial_sequence('persons','id'));
चेतावनी:currval()
INSERT
. के बाद ही काम करता है (जिसने nextval()
executed क्रियान्वित किया है ), उसी सत्र में ।
विकल्प 2:LASTVAL();
यह पिछले के समान है, केवल आपको अनुक्रम नाम निर्दिष्ट करने की आवश्यकता नहीं है:यह सबसे हाल ही में संशोधित अनुक्रम (हमेशा आपके सत्र के अंदर, ऊपर जैसा ही चेतावनी) की तलाश करता है।
दोनों CURRVAL
और LASTVAL
पूरी तरह से समवर्ती सुरक्षित हैं। पीजी में अनुक्रम का व्यवहार इस तरह से डिज़ाइन किया गया है कि अलग-अलग सत्र में हस्तक्षेप नहीं होगा, इसलिए दौड़ की स्थिति का कोई खतरा नहीं है (यदि कोई अन्य सत्र मेरे INSERT और मेरे चयन के बीच एक और पंक्ति सम्मिलित करता है, तो भी मुझे मेरा सही मान मिलता है)।
हालांकि उनके पास एक सूक्ष्म संभावित समस्या है। यदि डेटाबेस में कुछ TRIGGER (या RULE) है, जो persons
में डालने पर तालिका, अन्य तालिकाओं में कुछ अतिरिक्त प्रविष्टियां करता है... फिर LASTVAL
शायद हमें गलत मूल्य देगा। समस्या CURRVAL
. के साथ भी हो सकती है , यदि अतिरिक्त प्रविष्टियां उन्हीं persons
. में की जाती हैं तालिका (यह बहुत कम सामान्य है, लेकिन जोखिम अभी भी मौजूद है)।
विकल्प 3:INSERT
RETURNING
. के साथ
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
आईडी प्राप्त करने का यह सबसे स्वच्छ, कुशल और सुरक्षित तरीका है। इसमें पहले जैसा कोई जोखिम नहीं है।
कमियां? लगभग कोई नहीं:आपको अपने INSERT कथन को कॉल करने के तरीके को संशोधित करने की आवश्यकता हो सकती है (सबसे खराब स्थिति में, शायद आपकी API या DB परत INSERT से कोई मान वापस करने की अपेक्षा नहीं करती है); यह मानक एसक्यूएल नहीं है (कौन परवाह करता है); यह Postgresql 8.2 (दिसंबर 2006...) से उपलब्ध है
निष्कर्ष:यदि आप कर सकते हैं, तो विकल्प 3 के लिए जाएं। कहीं और, 1. को प्राथमिकता दें।
नोट:ये सभी तरीके बेकार हैं यदि आप विश्व स्तर पर अंतिम सम्मिलित आईडी प्राप्त करना चाहते हैं (जरूरी नहीं कि आपके सत्र से)। इसके लिए आपको SELECT max(id) FROM table
का सहारा लेना होगा (बेशक, यह अन्य लेनदेन से अप्रतिबद्ध प्रविष्टियां नहीं पढ़ेगा)।
इसके विपरीत, आपको कभी नहीं . करना चाहिए SELECT max(id) FROM table
. का उपयोग करें इसके बजाय ऊपर दिए गए 3 विकल्पों में से एक, अपने INSERT
. द्वारा अभी-अभी जनरेट की गई आईडी प्राप्त करने के लिए कथन, क्योंकि (प्रदर्शन के अलावा) यह समवर्ती सुरक्षित नहीं है:आपके INSERT
. के बीच और आपका SELECT
हो सकता है कि किसी अन्य सत्र ने एक और रिकॉर्ड डाला हो।