क्या मैं किसी अन्य INSERT में INSERT ... RETURNING के रिटर्न मान का उपयोग कर सकता हूं?


86

क्या ऐसा कुछ संभव है?

INSERT INTO Table2 (val)
VALUES ((INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id));

पहली तालिका के संदर्भ में दूसरी तालिका में एक पंक्ति सम्मिलित करने के लिए मान के रूप में वापसी मूल्य का उपयोग करना पसंद है?

जवाबों:


103

आप ऐसा कर सकते हैं Postgres 9.1 के साथ शुरू:

with rows as (
INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id
)
INSERT INTO Table2 (val)
SELECT id
FROM rows

इस बीच, यदि आप केवल आईडी में रुचि रखते हैं, तो आप ट्रिगर के साथ ऐसा कर सकते हैं:

create function t1_ins_into_t2()
  returns trigger
as $$
begin
  insert into table2 (val) values (new.id);
  return new;
end;
$$ language plpgsql;

create trigger t1_ins_into_t2
  after insert on table1
for each row
execute procedure t1_ins_into_t2();

1
रिटर्निंग आईडी के बगल में मान कैसे डालें? उदाहरण के लिए: INSERT INTO TABLE2 (val1, val2, val3) (1, 2, चयन आईडी पंक्तियों से)
महमूद हनफी

@ ममदौहनाफ़ी: आजकल के rowsसाथ (some_query returning ...)काम करना (आजमाया हुआ नहीं है)।
डेनिस डे बर्नार्डी

2
@ ममौदहनाफी: रिटर्निंग आईडी के बगल में मान डालने के लिए आप कुछ ऐसा कर सकते हैं: INSERT INTO TABLE2 (val1, val2, val3) SEL id, 1, 2 FROM पंक्तियों से
भिन्डी

upvoted! क्या यह परमाणु अर्थ है यदि पहला सम्मिलित सफल होता है और दूसरा क्या नहीं होता है?
पाइरेटऐप

2
@PirateApp बस परीक्षण किया गया! v12.4। पहला INSERT वास्तव में रोल-समर्थित है अगर दूसरा विफल रहता है, लेकिन पहले INSERT की श्रृंखला /
स्वत: अंकन

57

इस स्थिति के लिए सबसे अच्छा अभ्यास। का उपयोग करें RETURNING … INTO

INSERT INTO teams VALUES (...) RETURNING id INTO last_id;

ध्यान दें यह PLPGSQL के लिए है


3
क्या यह वास्तव में एक बात है? आप जिस डॉक से जुड़े हैं उसका कोई भी हिस्सा उल्लेख नहीं करता है RETURNING ... INTO
एलेक

4
@ एलेक: मुझे इस जवाब में यह दस्तावेज मिला ।
बार्ट हॉफलैंड

@ProroD: यह करता है।
बार्ट हॉफलैंड

13

डेनिस डे बर्नार्डी द्वारा दिए गए उत्तर के अनुरूप।

यदि आप आईडी को बाद में भी लौटा देना चाहते हैं और तालिका 2 में और चीजें डालना चाहते हैं:

with rows as (
INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id
)
INSERT INTO Table2 (val, val2, val3)
SELECT id, 'val2value', 'val3value'
FROM rows
RETURNING val

10
DO $$
DECLARE tableId integer;
BEGIN
  INSERT INTO Table1 (name) VALUES ('a_title') RETURNING id INTO tableId;
  INSERT INTO Table2 (val) VALUES (tableId);
END $$;

Psql के साथ परीक्षण किया गया (10.3, सर्वर 9.6.8)


8

आप lastval()फ़ंक्शन का उपयोग कर सकते हैं :

nextvalकिसी भी अनुक्रम के साथ हाल ही में प्राप्त किया गया मान लौटाएं

तो कुछ इस तरह:

INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val)  VALUES (lastval());

यह तब तक ठीक रहेगा जब तक कोई कॉल नहीं करता nextval() आपके INSERT के बीच किसी भी अन्य अनुक्रम (वर्तमान सत्र में) पर कोई ।

जैसा कि डेनिस ने नीचे उल्लेख किया है और मैंने ऊपर के बारे में चेतावनी दी है, lastval()अगर nextval()आपके INSERTs के बीच एक और अनुक्रम का उपयोग करके एक्सेस किया जाता है, तो आप मुसीबत में पड़ सकते हैं । ऐसा तब हो सकता है जब Table1उस पर INSERT ट्रिगर होता है जिसे मैन्युअल रूप से nextval()एक अनुक्रम पर बुलाया जाता है या अधिक संभावना है, एक INSERT एक मेज पर SERIALयाBIGSERIAL प्राथमिक कुंजी के साथ किया था। यदि आप वास्तव में पागल होना चाहते हैं (एक अच्छी बात, वे वास्तव में आप सभी के बाद आपको प्राप्त करने के लिए हैं), तो आप उपयोग कर सकते हैं, currval()लेकिन आपको संबंधित अनुक्रम का नाम जानना होगा:

INSERT INTO Table1 (name) VALUES ('a_title');
INSERT INTO Table2 (val)  VALUES (currval('Table1_id_seq'::regclass));

स्वचालित रूप से उत्पन्न अनुक्रम आमतौर पर नामित किया गया है t_c_seqजहां tतालिका नाम और cस्तंभ नाम है, लेकिन आप हमेशा में जाकर पता कर सकते हैं psqlऔर कह रही:

=> \d table_name;

और फिर प्रश्न में कॉलम के लिए डिफ़ॉल्ट मान को देखते हुए, उदाहरण के लिए:

id | integer | not null default nextval('people_id_seq'::regclass)

FYI करें: lastval()कम या ज्यादा, MySQL का PostgreSQL संस्करण LAST_INSERT_ID। मैं केवल इस बात का उल्लेख करता हूं क्योंकि बहुत सारे लोग MySQL से PostgreSQL की तुलना में अधिक परिचित हैं, इसलिए lastval()किसी परिचित से लिंक करना चीजों को स्पष्ट कर सकता है।


2
टेबल 1 पर ट्रिगर बाद में आवेषण करता है, तो बेहतर उपयोग करें।
डेनिस डे बर्नार्डी

@ डेनिस: सच है, लेकिन फिर आपको अनुक्रम के नाम की आवश्यकता है। मैं सभी आधारों को कवर करने के लिए उस प्रभाव में थोड़ा अपडेट जोड़ूंगा।
म्यू बहुत छोटा है

LASTVAL () और CURRVAL () दोनों वर्तमान डेटाबेस कनेक्शन के लिए काम करते हैं, अन्य कनेक्शन के लिए नहीं। अन्य उपयोगकर्ता अनुक्रम समय पर अपडेट कर सकते हैं, जो आपके परिणामों को नहीं बदलेगा। दूसरों की चिंता न करें, वे LASTVAL और / CURRVAL के लिए आपके परिणाम कभी नहीं बदलेंगे। LASTVAL और CURRVAL का उपयोग बिना किसी कनेक्शन के कनेक्शन का उपयोग करते समय बिल्कुल भी नहीं किया जा सकता है, जब चीजें गलत हो जाती हैं: आप डेटाबेस कनेक्शन को नियंत्रित नहीं करते हैं।
फ्रैंक हाइकेन्स

1
@ फ्रेंक: हाँ, वे सभी सत्र विशिष्ट हैं, लेकिन इसके साथ समस्या lastvalयह है कि टेबल 1 पर AFS INSERT ट्रिगर से आपकी पीठ के पीछे एक अनुक्रम आधारित INSERT हो सकता है। यह वर्तमान सत्र में होगा और संभवतः, lastval()जब आप इसकी उम्मीद नहीं कर रहे हैं , तो बदल देंगे।
म्यू बहुत कम है

1

table_ex

आईडी डिफॉल्ट नेवल ('table_id_seq' :: regclass),

camp1 varchar

शिविर 2

INSERT INTO table_ex(camp1,camp2) VALUES ('xxx','123') RETURNING id 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.