คำถามนี้เก่า แต่ฉันรู้สึกว่ายังไม่ได้รับคำตอบที่ดีที่สุด
มีUPDATE
ไวยากรณ์ ... โดยไม่ระบุชื่อคอลัมน์หรือไม่?
วิธีแก้ปัญหาทั่วไปด้วยไดนามิก SQL
คุณไม่จำเป็นต้องทราบชื่อคอลัมน์ใด ๆ ยกเว้นคอลัมน์ที่ไม่ซ้ำกันเพื่อเข้าร่วม ( id
ในตัวอย่าง) ทำงานได้อย่างน่าเชื่อถือสำหรับกรณีมุมที่เป็นไปได้ที่ฉันคิดได้
สิ่งนี้เฉพาะสำหรับ PostgreSQL ฉันกำลังสร้างโค้ดไดนามิกตามinformation_schemaโดยเฉพาะตารางinformation_schema.columns
ซึ่งกำหนดไว้ในมาตรฐาน SQL และ RDBMS ที่สำคัญที่สุด (ยกเว้น Oracle) มีอยู่ แต่DO
คำสั่งที่มีโค้ดPL / pgSQL ที่เรียกใช้ไดนามิก SQL นั้นไม่ใช่ไวยากรณ์ 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
สำหรับทุกคอลัมน์ในa
แต่ไม่ใช่ในทางกลับกัน b
สามารถมีคอลัมน์เพิ่มเติม
WHERE b.id = 123
เป็นทางเลือกเพื่ออัปเดตแถวที่เลือก
SQL Fiddle
คำตอบที่เกี่ยวข้องพร้อมคำอธิบายเพิ่มเติม:
โซลูชันบางส่วนด้วย SQL ธรรมดา
พร้อมรายการคอลัมน์ที่แชร์
คุณยังคงต้องทราบรายชื่อคอลัมน์ที่ทั้งสองตารางใช้ร่วมกัน ด้วยทางลัดทางไวยากรณ์สำหรับการอัปเดตหลายคอลัมน์ - สั้นกว่าคำตอบอื่น ๆ ที่แนะนำในทุกกรณี
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;
SQL Fiddle
ไวยากรณ์นี้ถูกนำมาใช้กับ Postgres 8.2 ในปี 2006 ก่อนที่จะมีการถามคำถาม รายละเอียดในคู่มือ.
ที่เกี่ยวข้อง:
พร้อมรายการคอลัมน์ใน 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 <> fiddle ที่นี่
Old sqlfiddle
นี่คือมาตรฐาน SQL ยกเว้นFROM
ข้อ
มันทำงานเรื่องของคอลัมน์เป็นจริงในปัจจุบันไม่มีA
แต่แบบสอบถามไม่สามารถแยกแยะความแตกต่างระหว่างค่าเป็นศูนย์ที่เกิดขึ้นจริงและคอลัมน์ที่ขาดหายไปในA
ดังนั้นจึงเป็นที่เชื่อถือได้เฉพาะในกรณีที่คอลัมน์ทั้งหมดในจะมีการกำหนดA
NOT NULL
มีหลายรูปแบบที่เป็นไปได้ขึ้นอยู่กับสิ่งที่คุณรู้เกี่ยวกับทั้งสองตาราง