Вопрос старый, но я чувствовал, что лучший ответ еще не дан.
Существует ли синтаксис ОБНОВЛЕНИЕ ... без указания имен столбцов ?
Общее решение с динамическим SQL
Вам не нужно знать имена столбцов, за исключением некоторых уникальных столбцов, к которым нужно присоединиться (id
в примере). Надежно работает для любого возможного углового случая, о котором я только могу подумать.
Это специфично для PostgreSQL. Я строю динамический код на основе information_schema , в частности таблицы information_schema.columns
, которая определена в ANSI 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 года, задолго до того, как был задан вопрос.
Более подробная информация в руководстве и соответствующий ответ на dba.SE:
Со списком столбцов в 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
во внешнем запросе.
Скрипка SQL.
Это стандартный SQL , за исключением предложения FROM
.
Он работает независимо от того, какой из столбцов действительно присутствует в A
, но запрос не может различить фактические значения NULL и отсутствующие столбцы в A
, поэтому он надежен только в том случае, если все столбцы в A
определены NOT NULL
.
Существует несколько возможных вариантов, в зависимости от того, что вы знаете об обеих таблицах.