31

का उपयोग कर एक समय में 3 टेबल में डेटा डालें, मैं एक क्वेरी के साथ 3 टेबल में डेटा डालना चाहता हूं।
मेरे टेबल लग रहा है नीचे की तरह:पोस्टग्रेस

CREATE TABLE sample (
    id  bigserial PRIMARY KEY, 
    lastname varchar(20), 
    firstname varchar(20) 
); 

CREATE TABLE sample1(
    user_id bigserial PRIMARY KEY, 
    sample_id bigint REFERENCES sample, 
    adddetails varchar(20) 
); 

CREATE TABLE sample2(
    id  bigserial PRIMARY KEY, 
    user_id bigint REFERENCES sample1, 
    value varchar(10) 
); 

मैं हर प्रविष्टि के लिए बदले में एक महत्वपूर्ण हो जाएगा और मैं अगले तालिका में उस कुंजी डालना होगा।
मेरे प्रश्न है:

insert into sample(firstname,lastname) values('fai55','shaggk') RETURNING id; 
insert into sample1(sample_id, adddetails) values($id,'ss') RETURNING user_id; 
insert into sample2(user_id, value) values($id,'ss') RETURNING id; 

लेकिन अगर मैं एक क्वेरी चला वे सिर्फ मेरे लिए मान और मैं तुरंत अगले क्वेरी में उन्हें पुन: उपयोग नहीं कर सकते।

इसे कैसे प्राप्त करें?

उत्तर

1

आप अन्य दो तालिकाओं में सम्मिलित करने के लिए नमूना तालिका पर सम्मिलित ट्रिगर के बाद एक बना सकते हैं।

ऐसा करने के साथ मुझे एकमात्र मुद्दा यह है कि आपके पास अतिरिक्त विवरण डालने का कोई तरीका नहीं है, यह हमेशा खाली होगा या इस मामले में एसएस। नमूना में एक कॉलम डालने का कोई तरीका नहीं है जो नमूना तालिका में वास्तव में नहीं है, इसलिए आप इसे सहज डालने के साथ भेज नहीं सकते हैं।

एक और विकल्प आपके आवेषण चलाने के लिए संग्रहीत प्रक्रिया बनाना होगा।

आपके पास प्रश्न है mysql और postgressql जिस डेटाबेस पर हम यहां बात कर रहे हैं?

8

कुछ इस

with first_insert as (
    insert into sample(firstname,lastname) 
    values('fai55','shaggk') 
    RETURNING id 
), 
second_insert as (
    insert into sample1(id ,adddetails) 
    values 
    ((select id from first_insert), 'ss') 
    RETURNING user_id 
) 
insert into sample2 (id ,adddetails) 
values 
((select user_id from first_insert), 'ss'); 

sample2 में डालने से उत्पन्न आईडी के रूप में की तरह की जरूरत नहीं है, मैं पिछले डालने से returning खंड हटा दिया।

60

उपयोग data-modifying CTEs:

WITH ins1 AS (
    INSERT INTO sample(firstname, lastname) 
    VALUES ('fai55', 'shaggk') 
-- ON  CONFLICT DO NOTHING    -- optional addition in Postgres 9.5+ 
    RETURNING id AS user_id 
    ) 
, ins2 AS (
    INSERT INTO sample1 (user_id, adddetails) 
    SELECT user_id, 'ss' FROM ins1 
    -- RETURNING user_id      -- only if used in turn 
    ) 
INSERT INTO sample2 (user_id, value)   -- same here 
SELECT user_id, 'ss' FROM ins1; 

प्रत्येक डालने से पहले एक पर निर्भर करता है। SELECTVALUES के बजाय यह सुनिश्चित करता है कि पिछली प्रविष्टि से कोई पंक्ति वापस नहीं आती है तो सहायक तालिकाओं में कुछ भी डाला नहीं गया है। (संबंधित: पोस्टग्रेस 9.5+ में ON CONFLICT खंड)
यह भी थोड़ा सा और तेज़ तरीका है।


आमतौर पर, यह अधिक सुविधाजनक है एक ही स्थान पर में पूरा डेटा पंक्तियों प्रदान करने के लिए:

WITH data(firstname, lastname, adddetails, value) AS (
    VALUES         -- provide data here 
     (text 'fai55', text 'shaggk', text 'ss', text 'ss2') -- see below 
     -- more?       -- works for multiple input rows 
    ) 
, ins1 AS (
    INSERT INTO sample (firstname, lastname) 
    SELECT firstname, lastname FROM data -- DISTINCT? see below 
    ON  CONFLICT DO NOTHING    -- required UNIQUE constraint 
    RETURNING firstname, lastname, id AS sample_id 
    ) 
, ins2 AS (
    INSERT INTO sample1 (sample_id, adddetails) 
    SELECT sample_id, adddetails 
    FROM data 
    JOIN ins1 USING (firstname, lastname) 
    RETURNING sample_id, user_id 
    ) 
INSERT INTO sample2 (user_id, value) 
SELECT user_id, value 
FROM data 
JOIN ins1 USING (firstname, lastname) 
JOIN ins2 USING (sample_id); 

आप के रूप में एक VALUES अभिव्यक्ति करने का विरोध एक अलग VALUES अभिव्यक्ति में स्पष्ट प्रकार डाले आवश्यकता हो सकती है (एक आईएनएसईआरटी से जुड़ा हुआ है, जहां डेटा प्रकार लक्ष्य तालिका से व्युत्पन्न होते हैं।

यदि एकाधिक पंक्तियां पहचान के साथ आ सकती हैं कैलोरी (firstname, lastname), आपको पहले डालने के लिए डुप्लिकेट गुना करना पड़ सकता है:

... 
INSERT INTO sample (firstname, lastname) 
SELECT DISTINCT firstname, lastname FROM data 
... 

आप डेटा स्रोत के बजाय CTE data के रूप में एक (अस्थायी) तालिका इस्तेमाल कर सकते हैं।

संबंधित अधिक विवरण के साथ:

+0

thanx मैं अगर किसी भी असफल प्रविष्टि .yes होता है बाहर लेनदेन रोल में जोड़ सकते हैं मैं कैसे – Faisal

+1

यह एक एकल एसक्यूएल बयान है कर सकते हैं। कोई भी एक ही लेनदेन में कई बयानों को बंडल कर सकता है, लेकिन कोई इसे विभाजित नहीं कर सकता है। इसके अलावा, डेनिस ने अपनी टिप्पणी में क्या कहा। और मैंने अपने जवाब के कुछ लिंक जोड़ दिए। –

+0

लेकिन क्या आपके पास सीटीई के अंदर एक चयन हो सकता है, और उसके बाद तुरंत INSERT के उपयोग के बाद? – mmcrae

4

आमतौर पर, आप जटिल प्रश्नों लेखन से बचने के लिए एक सौदे का उपयोग करेंगे।

http://www.postgresql.org/docs/current/static/sql-begin.html

http://dev.mysql.com/doc/refman/5.7/en/commit.html

तुम भी एक CTE इस्तेमाल कर सकते हैं, अपने Postgres टैग संभालने सही है। उदाहरण के लिए: पुनरावृत्ति के लिए

with sample_ids as (
    insert into sample(firstname, lastname) 
    values('fai55','shaggk') 
    RETURNING id 
), sample1_ids as (
    insert into sample1(id, adddetails) 
    select id,'ss' 
    from sample_ids 
    RETURNING id, user_id 
) 
insert into sample2(id, user_id, value) 
select id, user_id, 'val' 
from sample1_ids 
RETURNING id, user_id; 
+0

thanx मैं कैसे यदि कोई सम्मिलन विफल रहता है तो इस क्वेरी में लेनदेन प्राप्त करें, मैं रोलबैक – Faisal

+0

कर सकता हूं, फिर पाठ्यक्रम की क्वेरी को सही करने के बाद, आप सब कुछ फिर से शुरू करते हैं, क्योंकि संपूर्ण लेनदेन (या सीटीई) वापस लुढ़का जाएगा। बीटीडब्ल्यू, यदि आपके आवेषण कभी-कभी असफल होते हैं, तो आप शायद कुछ गलत कर रहे हैं। एकमात्र मामला जहां असफल होने के लिए उचित है, एक अपरिवर्तनीय परिदृश्य में है जो समवर्ती लेनदेन के दौरान डुप्लिकेट अद्वितीय कुंजी में चलाता है, और फिर भी आपको सलाहकार लॉक या टेबल लॉक मिल सकता है यदि आपको चीजों को बुलेट प्रूफ बनाने की आवश्यकता है। –