SQL एक तालिका के फ़ील्ड को दूसरे के फ़ील्ड से अपडेट करता है


124

मेरे पास दो टेबल हैं:

A [ID, column1, column2, column3]
B [ID, column1, column2, column3, column4]

Aहमेशा के सबसेट होगा B(जिसका अर्थ है कि सभी कॉलम Aभी हैं B)।

मैं एक विशिष्ट के साथ एक रिकॉर्ड को अपडेट करना चाहते IDमें Bसे अपने डेटा के साथ Aके सभी स्तंभों के लिए A। इस IDमें दोनों मौजूद है Aऔर B

क्या कोई UPDATEसिंटैक्स या कोई अन्य तरीका है कि कॉलम नामों को निर्दिष्ट किए बिना, केवल "ए के सभी कॉलम सेट करें" कह रहा है ?

मैं PostgreSQL का उपयोग कर रहा हूं, इसलिए एक विशिष्ट गैर-मानक कमांड भी स्वीकार किया जाता है (हालांकि, पसंदीदा नहीं)।


मुझे लगता है कि यह वही है जो आप करना चाहते हैं, dba.stackexchange.com/a/58383
-0

जवाबों:


234

आप गैर-मानक FROM क्लॉज का उपयोग कर सकते हैं ।

UPDATE b
SET column1 = a.column1,
  column2 = a.column2,
  column3 = a.column3
FROM a
WHERE a.id = b.id
AND b.id = 1

9
प्रश्न सभी स्तंभ नामों को निर्दिष्ट किए बिना इसे कैसे करें के बारे में पूछ रहा है । (और मैं भी हूं।)
क्लूसक

2
मैं @cluesque से सहमत हूं, लेकिन यह उत्तर किसी तालिका में एक स्तंभ में मानों को किसी अन्य तालिका में किसी स्तंभ में मान बदलने के लिए लुकअप तालिका के रूप में उपयोग करने का एक उत्कृष्ट तरीका है ( SO 21657475 देखें ), इसलिए +1 ...
विक्टोरिया स्टुअर्ट

1
B.id = 1 की आवश्यकता क्यों है?
यासिरज़गर

1
@YasirAzgar b.id = 1 को सीमित करना है कि b में कौन सी पंक्तियाँ अद्यतन की गई हैं। अन्यथा हम तालिका में हर पंक्ति को अपडेट करेंगे। कभी-कभी, यह वही हो सकता है जो आप चाहते हैं। लेकिन मूल प्रश्न बी में एक विशिष्ट पंक्ति को अद्यतन करने का था।
स्कॉट बेली

यह वही है जो मुझे अपनी विशेष समस्या के लिए चाहिए था: एक तालिका के कॉलम को किसी अन्य तालिका के अलग-अलग नाम वाले कॉलम से मानों के साथ अद्यतन करना।
मुआद-दवेब

49

सवाल पुराना है, लेकिन मुझे लगा कि सबसे अच्छा जवाब नहीं दिया गया है, फिर भी।

क्या कॉलम नामों को निर्दिष्ट किए बिना एक UPDATEवाक्यविन्यास है ... ?

डायनेमिक SQL के साथ सामान्य समाधान

इसमें शामिल होने के लिए आपको कुछ अद्वितीय स्तंभों को छोड़कर किसी भी स्तंभ के नाम को जानने की आवश्यकता नहीं है (id उदाहरण में) । किसी भी संभावित कोने के मामले में मज़बूती से काम कर सकता हूँ।

यह PostgreSQL के लिए विशिष्ट है। मैं information_schema के आधार पर डायनामिक कोड बना रहा हूं , विशेष रूप से तालिका में information_schema.columns, जो कि SQL मानक में परिभाषित है और अधिकांश प्रमुख RDBMS (Oracle को छोड़कर) है। लेकिन पीएल / pgSQL कोड के DOसाथ एक बयान गतिशील एसक्यूएल निष्पादित पूरी तरह से गैर-मानक PostgreSQL सिंटैक्स है।

DO
$do$
BEGIN

EXECUTE (
SELECT
  'UPDATE b
   SET   (' || string_agg(        quote_ident(column_name), ',') || ')
       = (' || string_agg('a.' || quote_ident(column_name), ',') || ')
   FROM   a
   WHERE  b.id = 123
   AND    a.id = b.id'
FROM   information_schema.columns
WHERE  table_name   = 'a'       -- table name, case sensitive
AND    table_schema = 'public'  -- schema name, case sensitive
AND    column_name <> 'id'      -- all columns except id
);

END
$do$;

हर कॉलम के bलिए एक मिलान कॉलम मान लें , लेकिन दूसरे तरीके से नहीं।abअतिरिक्त कॉलम हो सकते हैं।

WHERE b.id = 123 वैकल्पिक है, चयनित पंक्ति को अद्यतन करने के लिए।

एसक्यूएल फिडल।

अधिक स्पष्टीकरण के साथ संबंधित जवाब:

सादे एसक्यूएल के साथ आंशिक समाधान

साझा कॉलम की सूची के साथ

आपको अभी भी उन स्तंभ नामों की सूची जानने की आवश्यकता है जो दोनों तालिकाएं साझा करती हैं। कई कॉलमों को अपडेट करने के लिए एक सिंटैक्स शॉर्टकट के साथ - किसी भी मामले में अब तक सुझाए गए अन्य उत्तरों से कम।

UPDATE b
SET   (  column1,   column2,   column3)
    = (a.column1, a.column2, a.column3)
FROM   a
WHERE  b.id = 123    -- optional, to update only selected row
AND    a.id = b.id;

एसक्यूएल फिडल।

यह वाक्यविन्यास 2006 में पोस्टग्रेज 8.2 के साथ पेश किया गया था, प्रश्न पूछने से पहले। मैनुअल में विवरण।

सम्बंधित:

में स्तंभों की सूची के साथ B

तो के सभी स्तंभों Aपरिभाषित कर रहे हैं NOT NULL(लेकिन जरूरी नहीं B),
और आप जानते हैं की स्तंभ नाम B(लेकिन जरूरी नहीं A)।

UPDATE b
SET   (column1, column2, column3, column4)
    = (COALESCE(ab.column1, b.column1)
     , COALESCE(ab.column2, b.column2)
     , COALESCE(ab.column3, b.column3)
     , COALESCE(ab.column4, b.column4)
      )
FROM (
   SELECT *
   FROM   a
   NATURAL LEFT JOIN  b -- append missing columns
   WHERE  b.id IS NULL  -- only if anything actually changes
   AND    a.id = 123    -- optional, to update only selected row
   ) ab
WHERE b.id = ab.id;

NATURAL LEFT JOINसे एक पंक्ति में शामिल bहै, जहां एक ही नाम के सभी स्तंभों को एक ही मान हो। हमें इस मामले में एक अद्यतन की आवश्यकता नहीं है (कुछ भी नहीं बदलता है) और प्रक्रिया में उन पंक्तियों को जल्दी से समाप्त कर सकता है ( WHERE b.id IS NULL)।
हमें अभी भी एक मिलान पंक्ति खोजने की आवश्यकता है, इसलिएb.id = ab.id बाहरी क्वेरी में।

db <> फिडेल यहाँ
पुराना फिडेल sqlfiddle।

यह क्लॉज को छोड़करFROM मानक SQL है ।
इससे कोई फर्क नहीं पड़ता कि कौन से स्तंभ वास्तव में मौजूद हैं A, लेकिन क्वेरी वास्तविक NULL मानों और अनुपलब्ध स्तंभों के बीच अंतर नहीं कर सकती है A, इसलिए यह केवल विश्वसनीय है यदि सभी स्तंभों Aको परिभाषित किया गया हैNOT NULL

दोनों तालिकाओं के बारे में आप जो जानते हैं उसके आधार पर कई संभावित भिन्नताएं हैं ।


SQL की शक्ति! बस जब आप सेट क्लॉज में कोष्ठक जोड़ते हैं तो ध्यान दें ( SET (column1) = (a.column)) पोस्टग्रैज इसे एक अन्य प्रकार के अपडेट के रूप में मानेगा और इस तरह की त्रुटि और त्रुटि देगा:source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression
एडगर ओर्टेगा

26

मैं आईबीएम DB2 डेटाबेस के साथ काम कर रहा है और फिर दशक के लिए अब PostgreSQL सीखने की कोशिश कर रहा है।

यह PostgreSQL 9.3.4 पर काम करता है, लेकिन DB2 10.5 पर काम नहीं करता है:

UPDATE B SET
     COLUMN1 = A.COLUMN1,
     COLUMN2 = A.COLUMN2,
     COLUMN3 = A.COLUMN3
FROM A
WHERE A.ID = B.ID

नोट: मुख्य समस्या FROM कारण है जो DB2 में समर्थित नहीं है और ANSI SQL में भी नहीं है।

यह DB2 10.5 पर काम करता है, लेकिन PostgreSQL 9.3.4 पर काम नहीं करता है:

UPDATE B SET
    (COLUMN1, COLUMN2, COLUMN3) =
               (SELECT COLUMN1, COLUMN2, COLUMN3 FROM A WHERE ID = B.ID)

आखिरकार! यह PostgreSQL 9.3.4 और DB2 10.5 दोनों पर काम करता है:

UPDATE B SET
     COLUMN1 = (SELECT COLUMN1 FROM A WHERE ID = B.ID),
     COLUMN2 = (SELECT COLUMN2 FROM A WHERE ID = B.ID),
     COLUMN3 = (SELECT COLUMN3 FROM A WHERE ID = B.ID)

3
ध्यान दें कि दूसरा और तीसरा प्रश्न पूरी तरह से पहले के बराबर नहीं हैं। यदि कोई मिलान पंक्ति नहीं मिलती है B, तो पहला कथन कुछ भी नहीं करता है (मूल पंक्ति अछूती नहीं रहती है), जबकि अन्य दो ओवरले कॉलम NULL मानों के साथ हैं।
इरविन ब्रान्डेसटेटर

7

यह एक बड़ी मदद है। कोड

UPDATE tbl_b b
SET   (  column1,   column2,   column3)
    = (a.column1, a.column2, a.column3)
FROM   tbl_a a
WHERE  b.id = 1
AND    a.id = b.id;

अच्छी तरह से काम।

ध्यान दिया कि आपको एक ब्रैकेट की आवश्यकता है "" में

From "tbl_a" a

यह काम करने के लिए।


5

जरूरी नहीं कि आपने जो पूछा हो, लेकिन हो सकता है कि पोस्टग्रेज इनहेरिटेंस का उपयोग करने से मदद मिल सकती है?

CREATE TABLE A (
    ID            int,
    column1       text,
    column2       text,
    column3       text
);

CREATE TABLE B (
    column4       text
) INHERITS (A);

यह बी को अद्यतन करने की आवश्यकता से बचा जाता है।

लेकिन सभी विवरणों को पढ़ना सुनिश्चित करें ।

अन्यथा, आप जो मांगते हैं वह एक अच्छा अभ्यास नहीं माना जाता है - गतिशील सामान जैसे विचार SELECT * ...हतोत्साहित होते हैं (जैसे कि थोड़ी सी सुविधा मदद की चीजों से अधिक चीजों को तोड़ सकती है), और आप जो मांगते हैं वह UPDATE ... SETकमांड के लिए बराबर होगा ।


मुझे यकीन नहीं है कि वंशानुक्रम यह कैसे हल करेगा। क्या आपका मतलब ए के लिए एक अपडेट ट्रिगर जोड़ना है जो बी को भी अपडेट करता है? मैं केवल अनुरोध पर, बी के साथ हर समय ए को सिंक्रनाइज़ नहीं करना चाहता। और ऐसे मामले में, मैं ट्रिगर्स का उपयोग नहीं कर सकता।
Nir

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

0

आप ऐसा करने के लिए गतिशील sql का निर्माण और निष्पादन कर सकते हैं, लेकिन यह वास्तव में आदर्श नहीं है


मैंने उसके बारे में सोचा। मुझे लगा कि मैं बाद में दोनों तालिकाओं में परिवर्तन के साथ अपनी क्वेरी का अनुपालन कर सकता हूं, लेकिन गतिशील sql लगता है कि सभी क्षेत्रों को निर्दिष्ट करने और आगे की संगतता के बारे में भूल जाने की तुलना में बहुत जटिल है।
Nir

हां, यह जटिल होगा, लेकिन बाद के कॉलमों को जोड़ने या हटाने के साथ संगत होना चाहिए। आपको दोनों तालिकाओं से कॉलम नाम प्राप्त करने के लिए पहले एक क्वेरी करनी होगी, फिर कॉलम नामों से मिलान करना होगा और फिर मिलान कॉलम नामों के आधार पर अपडेट करने के लिए डायनामिक sql लिखना होगा। एक मजेदार परियोजना वास्तव में :)
डेनियल ब्रिंक

-4

निम्नलिखित का प्रयास करें

Update A a, B b, SET a.column1=b.column1 where b.id=1

EDITED: - एक से अधिक कॉलम अपडेट करें

Update A a, B b, SET a.column1=b.column1, a.column2=b.column2 where b.id=1

मुझे समझ नहीं आ रहा है कि यह कॉलम 1, कॉलम 2 और कॉलम 3 को कैसे कॉपी करता है। और मुझे स्तंभ 1 का स्पष्ट उल्लेख करने की आवश्यकता है।
Nir

मेरे लिए काम नहीं करता है। मुझे निम्न त्रुटि मिलती है: ERROR: सिंटैक्स त्रुटि पर या उसके पास ","
मेलबिक

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