Ответ 1
Вы можете использовать нестандартное FROM.
UPDATE b
SET column1 = a.column1,
column2 = a.column2,
column3 = a.column3
FROM a
WHERE a.id = b.id
AND b.id = 1
У меня есть две таблицы:
A [ID, column1, column2, column3]
B [ID, column1, column2, column3, column4]
A
всегда будет подмножеством B
(что означает, что все столбцы A
также находятся в B
).
Я хочу обновить запись с помощью определенного ID
в B
с их данными из A
для всех столбцов A
. Этот ID
существует как в A
, так и B
.
Есть ли синтаксис UPDATE
или любой другой способ сделать это без указания имен столбцов, просто говоря "установить все столбцы A"?
Я использую PostgreSQL, поэтому также принимается определенная нестандартная команда (однако, не рекомендуется).
Вы можете использовать нестандартное FROM.
UPDATE b
SET column1 = a.column1,
column2 = a.column2,
column3 = a.column3
FROM a
WHERE a.id = b.id
AND b.id = 1
Вопрос старый, но я чувствовал, что лучший ответ еще не дан.
Существует ли синтаксис
UPDATE
... без указания имен столбцов?
Вам не нужно знать имена столбцов, за исключением некоторых уникальных столбцов, к которым нужно присоединиться (id
в примере). Надежно работает для любого возможного angular случая, который я могу придумать.
Это специфично для PostgreSQL. Я строю динамический код на основе information_schema, в частности таблицы information_schema.columns
, которая определена в стандарте ISO 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
является необязательным, чтобы обновить только выбранную строку.
Связанные ответы с более подробным объяснением:
Вам все еще нужно знать список имен столбцов, которые разделяют обе таблицы. С синтаксической комбинацией для обновления нескольких столбцов - короче, чем предлагали другие ответы в любом случае.
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;
Этот синтаксис был введен в Postgres 8.2 в декабре 2006 года, задолго до того, как был задан вопрос.
Подробнее в руководстве и связанных с этим ответах на dba.SE:
B
Если определены все столбцы A
are defined 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 & lt;> скрипка здесь
Старый sqlfiddle.
Это стандартный SQL за исключением условия FROM
.
Он работает независимо от того, какой из столбцов действительно присутствует в A
, но запрос не может различить фактические значения NULL и отсутствующие столбцы в A
, поэтому он надежен только в том случае, если определены все столбцы в A
NOT NULL
.
Есть несколько возможных вариантов, в зависимости от того, что вы знаете об обеих таблицах.
Я работаю с базой данных IBM DB2 более десятилетия и теперь пытаюсь изучить PostgreSQL.
Он работает на PostgreSQL 9.3.4, но не работает на DB2 10.5:
UPDATE B SET
COLUMN1 = A.COLUMN1,
COLUMN2 = A.COLUMN2,
COLUMN3 = A.COLUMN3
FROM A
WHERE A.ID = B.ID
Примечание. Основная проблема - причина FROM, которая не поддерживается в DB2, а также не в ANSI SQL.
Он работает с DB2 10.5, но не работает над PostgreSQL 9.3.4:
UPDATE B SET
(COLUMN1, COLUMN2, COLUMN3) =
(SELECT COLUMN1, COLUMN2, COLUMN3 FROM A WHERE ID = B.ID)
НАКОНЕЦ! Он работает как на PostgreSQL 9.3.4, так и на DB2 10.5:
UPDATE B SET
COLUMN1 = (SELECT COLUMN1 FROM A WHERE ID = B.ID),
COLUMN2 = (SELECT COLUMN2 FROM A WHERE ID = B.ID),
COLUMN3 = (SELECT COLUMN3 FROM A WHERE ID = B.ID)
Это отличная помощь. Код
UPDATE tbl_b b
SET ( column1, column2, column3)
= (a.column1, a.column2, a.column3)
FROM tbl_a a
WHERE b.id = 1
AND a.id = b.id;
отлично работает.
отметил, что вам нужна скобка "" в
From "tbl_a" a
чтобы он работал.
Не обязательно то, что вы просили, но, возможно, использование наследования postgres могло бы помочь?
CREATE TABLE A (
ID int,
column1 text,
column2 text,
column3 text
);
CREATE TABLE B (
column4 text
) INHERITS (A);
Это позволяет избежать необходимости обновления B.
Но не забудьте прочитать все подробности.
В противном случае то, что вы просите, не считается хорошей практикой - динамические вещи, такие как представления с SELECT * ...
, обескуражены (поскольку такое небольшое удобство может сломать больше вещей, чем помогать чему-либо), и то, что вы просите, будет эквивалентно команда UPDATE ... SET
.
вы можете создавать и выполнять динамический sql для этого, но его действительно не идеальный
Попробуйте следовать
Update A a, B b, SET a.column1=b.column1 where b.id=1
EDITED: - обновить более одного столбца
Update A a, B b, SET a.column1=b.column1, a.column2=b.column2 where b.id=1