Câu hỏi đã cũ nhưng tôi cảm thấy câu trả lời hay nhất chưa được đưa ra.
Có một UPDATE
cú pháp ... mà không chỉ định tên cột ?
Giải pháp chung với SQL động
Bạn không cần biết bất kỳ tên cột nào ngoại trừ một số cột duy nhất để tham gia (id
trong ví dụ). Hoạt động đáng tin cậy cho bất kỳ trường hợp góc có thể tôi có thể nghĩ đến.
Điều này là cụ thể cho PostgreSQL. Tôi đang xây dựng mã động dựa trên information_schema , đặc biệt là bảng information_schema.columns
, được định nghĩa trong tiêu chuẩn SQL và hầu hết RDBMS chính (trừ Oracle) đều có nó. Nhưng một DO
câu lệnh với mã PL / pgSQL thực thi SQL động hoàn toàn là cú pháp PostgreQuery không chuẩn.
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$;
Giả sử một cột phù hợp b
cho mỗi cột trong a
, nhưng không phải là cách khác.b
có thể có các cột bổ sung.
WHERE b.id = 123
là tùy chọn, để cập nhật một hàng đã chọn.
Câu đố SQL.
Câu trả lời liên quan với nhiều lời giải thích:
Giải pháp một phần với SQL đơn giản
Với danh sách các cột được chia sẻ
Bạn vẫn cần biết danh sách các tên cột mà cả hai bảng chia sẻ. Với một phím tắt cú pháp để cập nhật nhiều cột - ngắn hơn những câu trả lời khác được đề xuất cho đến nay trong mọi trường hợp.
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;
Câu đố SQL.
Cú pháp này được giới thiệu với Postgres 8.2 vào năm 2006, rất lâu trước khi câu hỏi được hỏi. Chi tiết trong hướng dẫn.
Liên quan:
Với danh sách các cột trong B
Nếu tất cả các cột A
được xác định NOT NULL
(nhưng không nhất thiết B
)
và bạn biết tên cột của B
(nhưng không nhất thiết 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;
Các NATURAL LEFT JOIN
tham gia một hàng từ b
đó tất cả các cột cùng tên giữ các giá trị giống nhau. Chúng tôi không cần cập nhật trong trường hợp này (không có gì thay đổi) và có thể loại bỏ những hàng đó sớm trong quy trình ( WHERE b.id IS NULL
).
Chúng ta vẫn cần tìm một hàng phù hợp, vì vậyb.id = ab.id
trong truy vấn bên ngoài.
db <> fiddle ở đây
Cũ sqlfiddle .
Đây là SQL tiêu chuẩn ngoại trừ FROM
mệnh đề .
Nó hoạt động bất kể cột nào thực sự có mặt trong đó A
, nhưng truy vấn không thể phân biệt giữa các giá trị NULL thực tế và các cột bị thiếu A
, vì vậy nó chỉ đáng tin cậy nếu tất cả các cột trong A
được xác địnhNOT NULL
.
Có nhiều biến thể có thể, tùy thuộc vào những gì bạn biết về cả hai bảng.