Pytanie jest stare, ale czułem, że nie otrzymałem jeszcze najlepszej odpowiedzi.
Czy istnieje UPDATE
składnia ... bez określania nazw kolumn ?
Ogólne rozwiązanie z dynamicznym SQL
Nie musisz znać żadnych nazw kolumn poza kilkoma unikatowymi kolumnami, do których chcesz dołączyć ( id
w przykładzie). Działa niezawodnie w każdym możliwym przypadku narożnym, o którym mogę pomyśleć.
Jest to specyficzne dla PostgreSQL. Buduję kod dynamiczny w oparciu o schemat information_schema , w szczególności tabelę information_schema.columns
, która jest zdefiniowana w standardzie SQL i ma ją większość głównych RDBMS (poza Oracle). Ale DO
instrukcja z kodem PL / pgSQL wykonującym dynamiczny SQL jest całkowicie niestandardową składnią 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$;
Zakładając pasującą kolumnę w b
dla każdej kolumny w a
, ale nie odwrotnie. b
może mieć dodatkowe kolumny.
WHERE b.id = 123
jest opcjonalne, aby zaktualizować wybrany wiersz.
SQL Fiddle.
Powiązane odpowiedzi z dokładniejszym wyjaśnieniem:
Częściowe rozwiązania ze zwykłym SQL
Z listą wspólnych kolumn
Nadal musisz znać listę nazw kolumn, które współużytkują obie tabele. Ze skrótem do składni do aktualizowania wielu kolumn - w każdym przypadku krótszym niż sugerowały inne odpowiedzi.
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.
Ta składnia została wprowadzona w Postgres 8.2 w 2006 roku, na długo przed zadaniem pytania. Szczegóły w instrukcji.
Związane z:
Z listą kolumn w formacie B
Jeśli wszystkie kolumny A
są zdefiniowane NOT NULL
(ale nie koniecznie B
),
a ty znać nazwy kolumn z B
(ale nie koniecznie 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
Dołącza do wiersza z b
którym wszystkie kolumny o tej samej nazwie posiadają te same wartości. W tym przypadku nie potrzebujemy aktualizacji (nic się nie zmienia) i możemy wyeliminować te wiersze na wczesnym etapie procesu ( WHERE b.id IS NULL
).
Nadal musimy znaleźć pasujący wiersz, więc b.id = ab.id
w zewnętrznym zapytaniu.
db <> skrzypce tutaj
Stare sqlfiddle.
To jest standardowy SQL z wyjątkiem FROM
klauzuli .
Działa bez względu na to, która z kolumn jest faktycznie obecna w programie A
, ale zapytanie nie może odróżnić rzeczywistych wartości NULL od brakujących kolumn w A
, więc jest wiarygodne tylko wtedy, gdy A
zdefiniowane są wszystkie kolumny w NOT NULL
.
Istnieje wiele możliwych odmian, w zależności od tego, co wiesz o obu stołach.