La question est ancienne, mais j'ai eu le sentiment que la meilleure réponse n'avait pas encore été donnée.
Existe-t-il un UPDATE
syntaxe ... sans spécifier les noms des colonnes ?
Solution générale avec SQL dynamique
Connaissant uniquement la colonne de la clé primaire des deux tables
Vous n'avez pas besoin de connaître le nom des colonnes, à l'exception d'une ou plusieurs colonnes uniques sur lesquelles effectuer la jointure ( id
dans l'exemple). Ce système fonctionne de manière fiable dans tous les cas de figure auxquels je peux penser.
Ceci est spécifique à PostgreSQL. Je suis en train de construire un code dynamique basé sur le information_schema , en particulier le tableau information_schema.columns
qui est définie dans la norme SQL et que la plupart des principaux SGBDR (à l'exception d'Oracle) possèdent. Mais un DO
déclaration avec PL/pgSQL qui exécute du code SQL dynamique est une syntaxe totalement non standard de 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$;
En supposant qu'il existe une colonne correspondante dans b
pour tous colonne dans a
mais pas l'inverse. b
peut comporter des colonnes supplémentaires.
WHERE b.id = 123
est facultatif, pour mettre à jour une ligne sélectionnée.
_db<>fiddle aquí_
Ancienne <a href="http://sqlfiddle.com/#!17/cdd2b/3" rel="nofollow noreferrer">sqlfiddle</a>
Réponses connexes avec plus d'explications :
Solutions partielles avec SQL simple
Connaître la liste des colonnes partagées
Vous connaissez la liste des noms de colonnes que les deux tables partagent. Avec un raccourci syntaxique pour la mise à jour de plusieurs colonnes - plus court que ce que les autres réponses ont suggéré 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;
_db<>fiddle aquí_
Ancienne <a href="http://sqlfiddle.com/#!17/cdd2b/3" rel="nofollow noreferrer">sqlfiddle</a>
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 rapport :
Connaître la liste des colonnes dans B
Si toutes les colonnes de A
sont définis NOT NULL
(mais pas nécessairement toutes les colonnes de B
),
et vous connaissez les noms des colonnes de B
(mais pas nécessairement ceux de 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;
Les NATURAL LEFT JOIN
joint une ligne de b
où 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 nous pouvons éliminer ces lignes dès le 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 extérieure.
_db<>fiddle aquí_
Ancienne <a href="http://sqlfiddle.com/#!15/62fce/1" rel="nofollow noreferrer">sqlfiddle</a>
Il s'agit d'un code SQL standard à l'exception de la FROM
clause .
Cela fonctionne quelle que soit la colonne présente dans le fichier A
mais la requête ne peut pas faire la distinction entre les valeurs NULL réelles et les colonnes manquantes dans la base de données des A
Il n'est donc fiable que si toutes les colonnes de A
sont définis NOT NULL
.
Il existe de multiples variantes possibles, en fonction de ce que vous conozca sur les deux tables.