La domanda è vecchia ma sentivo che la risposta migliore non era stata ancora data.
Esiste una UPDATE
sintassi ... senza specificare i nomi delle colonne ?
Soluzione generale con SQL dinamico
Non è necessario conoscere alcun nome di colonna ad eccezione di alcune colonne univoche su cui unirsi ( id
nell'esempio). Funziona in modo affidabile per ogni possibile caso d'angolo a cui riesco a pensare.
Questo è specifico di PostgreSQL. Sto costruendo codice dinamico basato su information_schema , in particolare sulla tabella information_schema.columns
, che è definita nello standard SQL e la maggior parte dei principali RDBMS (eccetto Oracle) ce l'hanno. Ma DO
un'istruzione con codice PL / pgSQL che esegue SQL dinamico è una sintassi PostgreSQL totalmente non standard.
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$;
Supponendo una colonna corrispondente in b
per ogni colonna in a
, ma non il contrario. b
può avere colonne aggiuntive.
WHERE b.id = 123
è facoltativo, per aggiornare una riga selezionata.
SQL Fiddle.
Risposte correlate con ulteriori spiegazioni:
Soluzioni parziali con semplice SQL
Con elenco di colonne condivise
È ancora necessario conoscere l'elenco dei nomi di colonna condivisi da entrambe le tabelle. Con una scorciatoia sintattica per l'aggiornamento di più colonne, in ogni caso più breve di quanto suggerito finora dalle altre risposte.
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.
Questa sintassi è stata introdotta con Postgres 8.2 nel 2006, molto prima che venisse posta la domanda. Dettagli nel manuale.
Relazionato:
Con elenco di colonne in formato B
Se tutte le colonne di A
sono definite NOT NULL
(ma non necessariamente B
),
e si conoscono i nomi delle colonne di B
(ma non necessariamente 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;
Il NATURAL LEFT JOIN
unisce una riga da b
cui tutte le colonne con lo stesso nome contengono gli stessi valori. Non abbiamo bisogno di un aggiornamento in questo caso (non cambia nulla) e possiamo eliminare quelle righe all'inizio del processo ( WHERE b.id IS NULL
).
Abbiamo ancora bisogno di trovare una riga corrispondente, quindi b.id = ab.id
nella query esterna.
db <> fiddle qui
Vecchio sqlfiddle.
Questo è l'SQL standard ad eccezione della FROM
clausola .
Funziona indipendentemente da quale delle colonne sia effettivamente presente A
, ma la query non è in grado di distinguere tra i valori NULL effettivi e le colonne mancanti in A
, quindi è affidabile solo se tutte le colonne in A
sono definite NOT NULL
.
Ci sono più varianti possibili, a seconda di ciò che sai su entrambe le tabelle.