Вопрос старый, но я чувствовал, что лучшего ответа пока нет.
Есть ли UPDATE
синтаксис ... без указания имен столбцов ?
Общее решение с динамическим SQL
Вам не нужно знать какие-либо имена столбцов, кроме некоторых уникальных столбцов, к которым нужно присоединиться ( id
в примере). Работает надежно для любого возможного углового случая, о котором я могу подумать.
Это характерно для PostgreSQL. Я создаю динамический код на основе information_schema , в частности таблицы information_schema.columns
, которая определена в стандарте SQL, и большинство основных СУБД (кроме Oracle) имеют ее. Но DO
оператор с кодом PL / pgSQL, выполняющий динамический SQL, является совершенно нестандартным синтаксисом 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$;
Предполагая, что соответствующий столбец входит b
для каждого столбца в a
, но не наоборот. b
могут иметь дополнительные столбцы.
WHERE b.id = 123
не является обязательным, чтобы обновить выбранную строку.
SQL Fiddle.
Связанные ответы с дополнительными пояснениями:
Частичные решения с простым SQL
Со списком общих столбцов
Вам все еще нужно знать список имен столбцов, которые используются в обеих таблицах. С ярлыком синтаксиса для обновления нескольких столбцов - в любом случае короче, чем предлагали другие ответы.
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.
Этот синтаксис был представлен в Postgres 8.2 в 2006 году, задолго до того, как был задан вопрос. Подробности в инструкции.
Связанный:
Со списком столбцов в B
Если все столбцы A
определены NOT NULL
(но не обязательно B
),
и вы знаете имена столбцов B
(но не обязательно 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
к строке, в b
которой все столбцы с одинаковым именем содержат одинаковые значения. В этом случае нам не нужно обновление (ничего не меняется), и мы можем удалить эти строки на ранней стадии процесса ( WHERE b.id IS NULL
).
Нам все еще нужно найти соответствующую строку, поэтому b.id = ab.id
во внешнем запросе.
db <> fiddle here
Старый sqlfiddle.
Это стандартный SQL, за исключением FROM
предложения .
Он работает независимо от того, какие столбцы на самом деле присутствуют A
, но запрос не может различить фактические значения NULL и отсутствующие столбцы A
, поэтому он является надежным только в том случае, если все столбцы A
определены NOT NULL
.
Есть несколько возможных вариантов, в зависимости от того, что вы знаете об обеих таблицах.