Подтвердить что ты не робот

Поля SQL обновления одной таблицы из полей другого

У меня есть две таблицы:

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, поэтому также принимается определенная нестандартная команда (однако, не рекомендуется).

4b9b3361

Ответ 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

Ответ 2

Вопрос старый, но я чувствовал, что лучший ответ еще не дан.

Существует ли синтаксис UPDATE... без указания имен столбцов?

Общее решение с динамическим SQL

Вам не нужно знать имена столбцов, за исключением некоторых уникальных столбцов, к которым нужно присоединиться (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 является необязательным, чтобы обновить только выбранную строку.

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 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.

Есть несколько возможных вариантов, в зависимости от того, что вы знаете об обеих таблицах.

Ответ 3

Я работаю с базой данных 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)

Ответ 4

Это отличная помощь. Код

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

чтобы он работал.

Ответ 5

Не обязательно то, что вы просили, но, возможно, использование наследования postgres могло бы помочь?

CREATE TABLE A (
    ID            int,
    column1       text,
    column2       text,
    column3       text
);

CREATE TABLE B (
    column4       text
) INHERITS (A);

Это позволяет избежать необходимости обновления B.

Но не забудьте прочитать все подробности.

В противном случае то, что вы просите, не считается хорошей практикой - динамические вещи, такие как представления с SELECT * ..., обескуражены (поскольку такое небольшое удобство может сломать больше вещей, чем помогать чему-либо), и то, что вы просите, будет эквивалентно команда UPDATE ... SET.

Ответ 6

вы можете создавать и выполнять динамический sql для этого, но его действительно не идеальный

Ответ 7

Попробуйте следовать

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