La question est ancienne mais je sentais que la meilleure réponse n'avait pas encore été donnée.
Existe-t-il une UPDATE
syntaxe ... sans spécifier les noms des colonnes ?
Solution générale avec SQL dynamique
Vous n'avez pas besoin de connaître les noms de colonnes, à l'exception de certaines colonnes uniques à rejoindre ( id
dans l'exemple). Fonctionne de manière fiable pour tous les cas d'angle possibles auxquels je peux penser.
Ceci est spécifique à PostgreSQL. Je construis du code dynamique basé sur le schéma_information , en particulier la table information_schema.columns
, qui est définie dans la norme SQL et la plupart des grands SGBDR (sauf Oracle) l'ont. Mais une DO
instruction avec du code PL / pgSQL exécutant du SQL dynamique est une syntaxe PostgreSQL totalement 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$;
En supposant une colonne correspondante b
pour chaque colonne de a
, mais pas l'inverse. b
peut avoir des colonnes supplémentaires.
WHERE b.id = 123
est facultatif, pour mettre à jour une ligne sélectionnée.
SQL Fiddle.
Réponses connexes avec plus d'explications:
Solutions partielles avec SQL brut
Avec liste des colonnes partagées
Vous devez toujours connaître la liste des noms de colonnes que les deux tables partagent. Avec un raccourci de syntaxe pour mettre à jour plusieurs colonnes - plus court que ce que les autres réponses suggèrent jusqu'à présent dans tous les cas.
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.
Cette syntaxe a été introduite avec Postgres 8.2 en 2006, bien avant que la question ne soit posée. Détails dans le manuel.
En relation:
Avec la liste des colonnes dans B
Si toutes les colonnes de A
sont définies NOT NULL
(mais pas nécessairement B
),
et que vous connaissez les noms de colonnes de B
(mais pas nécessairement 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;
Le NATURAL LEFT JOIN
joint une ligne à partir de b
laquelle toutes les colonnes du même nom contiennent les mêmes valeurs. Nous n'avons pas besoin d'une mise à jour dans ce cas (rien ne change) et pouvons éliminer ces lignes au début du processus ( WHERE b.id IS NULL
).
Nous devons encore trouver une ligne correspondante, donc b.id = ab.id
dans la requête externe.
db <> violon ici
Ancien sqlfiddle.
Il s'agit du SQL standard à l' exception de la FROM
clause .
Cela fonctionne quelle que soit la colonne réellement présente dans A
, mais la requête ne peut pas faire la distinction entre les valeurs NULL réelles et les colonnes manquantes dans A
, elle n'est donc fiable que si toutes les colonnes de A
sont définies NOT NULL
.
Il existe plusieurs variantes possibles, en fonction de ce que vous savez sur les deux tables.