UPDATE भाग में स्रोत तालिका से मानों का उपयोग करते हुए CONFLICT के साथ UPSERT


18

दिया हुआ:

CREATE TABLE A (
PK_A INT8 NOT NULL,
A INT8,
PRIMARY KEY (PK_A)
);

CREATE TABLE B (
PK_B INT8 NOT NULL,
B INT8,
PRIMARY KEY (PK_B)
);

यह प्रश्न:

insert into table_b (pk_b, b) 
select pk_a,a from table_a 
on conflict (b) do update set b=a;

निम्नलिखित त्रुटि का कारण बनता है:

ERROR:  column "a" does not exist
LINE 1: ...elect pk_a,a from table_a on conflict (b) do update set b=a;
                                                                 ^
HINT:  There is a column named "a" in table "*SELECT*", but it cannot be referenced from this part of the query.

की सामग्री का संदर्भ देते हुए अद्यतन कैसे करें table_a?


5
CREATE TABLE A...तालिका बनाता है a, नहीं table_a
अबेलिस्टो

do update set b = a;नहीं मिल रहा है "एक" क्योंकि तालिका करने के लिए "बी" और नहीं Subquery के लिए वहाँ संदर्भ, कोशिशdo update set b = (select a from a);
Patrick7

जवाबों:


25

एकाधिक समस्याएं।
आपका सेटअप, विस्तारित:

CREATE TABLE a (
  pk_a int PRIMARY KEY 
, a int
, comment text  -- added column to make effect clear
);

CREATE TABLE b (
  pk_b int PRIMARY KEY
, b int 
, comment text
);

INSERT INTO a VALUES (1, 11, 'comment from a')
                   , (2, 22, 'comment from a');

INSERT INTO b VALUES (1, 77, 'comment from b');

यह काम:

INSERT INTO b (pk_b, b, comment) 
SELECT pk_a, a, comment
FROM   a 
ON     CONFLICT (pk_b) DO UPDATE  -- conflict is on the unique column
SET    b = excluded.b;            -- key word "excluded", refer to target column

परिणाम:

TABLE b;

 pk_b | b  |    comment
------+----+----------------
    1 | 11 | comment from b   -- updated
    2 | 22 | comment from a   -- inserted

समस्याये

  1. आप भ्रमित कर रहे हैं table_aऔर Aआपके डेमो में (जैसे @Abelisto ने टिप्पणी की )।

    कानूनी, निचले मामले का उपयोग करते हुए, अयोग्य पहचानकर्ता भ्रम से बचने में मदद करता है।

  2. जैसे @Ziggy का उल्लेख किया गया है , ON CONFLICTकेवल वास्तविक अद्वितीय या बहिष्करण बाधा के लिए काम करता है । नियम पुस्तिका:

    वैकल्पिक ON CONFLICTक्लॉज एक अद्वितीय उल्लंघन या अपवर्जन बाधा उल्लंघन त्रुटि को बढ़ाने के लिए एक वैकल्पिक कार्रवाई को निर्दिष्ट करता है।

    नतीजतन, ON CONFLICT (b)वहाँ काम नहीं कर सकता, कोई अड़चन नहीं। ON CONFLICT (pk_b)काम करता है।

  3. जैसे @Ziggy का भी उल्लेख किया गया है , स्रोत तालिका के नामUPDATE भाग में दिखाई नहीं देते हैंनियम पुस्तिका:

    SETऔर WHEREमें खंड ON CONFLICT DO UPDATEतालिका का नाम (या एक उपनाम) का उपयोग कर मौजूदा पंक्ति के लिए उपयोग किया है, और करने के लिए विशेष का उपयोग कर प्रविष्टि के लिए प्रस्तावित पंक्तियों excludedतालिका

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

  4. आप भाग में स्रोत तालिका के स्तंभ नामों का भी उपयोग नहीं कर सकते UPDATE। यह लक्ष्य पंक्ति का कॉलम नाम होना चाहिए । तो आप वास्तव में चाहते हैं:

    SET    b = excluded.b

    एक बार फिर मैनुअल:

    ध्यान दें कि सभी प्रति पंक्ति BEFORE INSERTट्रिगर के प्रभाव बहिष्कृत मूल्यों में परिलक्षित होते हैं, क्योंकि उन प्रभावों को सम्मिलन से बाहर जाने वाली पंक्ति में योगदान हो सकता है।


इस स्पष्टीकरण के लिए धन्यवाद, अब मुझे पता है कि b = excluded.aकाम क्यों नहीं किया जा सकता है, यह आधिकारिक दस्तावेज़ में थोड़ा छिपा हुआ था।
पैट्रिक

डमी के लिए सरल एक लाइनर जैसे: 'बहिष्कृत' नए आने वाले डेटा को इंगित करता है जिसे आप सम्मिलित करना चाहते हैं या तालिका में बने रहते हैं।
user92674

8

जब PostgreSQL 9.5+ में अपसर्ट कर रहे हैं, तो आपको अलग किए गए डेटा (जो डालने में विफल रहे) को संदर्भित करना चाहिए excluded। इसके अलावा, on conflictविकल्प को कुंजी को संदर्भित करना चाहिए: (pk_b)इसके बजाय (b)। उदाहरण के लिए।

insert into table_b (pk_b, b) 
select pk_a,a from table_a 
on conflict (pk_b) do update set b=excluded.b;

अधिक जानकारी के लिए आधिकारिक दस्तावेज या इस आसान परिचय को देखें


यह क्वेरी काम नहीं करती है।
shx
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.