Как я могу сделать инструкцию UPDATE с JOIN в SQL?

мне нужно обновить эту таблицу в SQL Server 2005 С данными из таблицы "родитель" см. ниже:

продажа

id (int)
udid (int)
assid (int)

ud

id  (int)
assid  (int)

sale.assid содержит правильное значение для обновления ud.assid.

какой запрос сделает это? Я думаю join но я не уверен, если это возможно.

14 ответов


синтаксис строго зависит от того, какие СУБД SQL вы используете. Вот несколько способов сделать это в ANSI/ISO (aka должен работать на любой СУБД SQL), MySQL, SQL Server и Oracle. Обратите внимание, что мой предлагаемый метод ANSI / ISO обычно будет намного медленнее, чем два других метода, но если вы используете СУБД SQL, отличную от MySQL, SQL Server или Oracle ,то это может быть единственный способ (например, если ваша СУБД SQL не поддерживает MERGE):

ANSI / ISO:

update ud 
     set assid = (
          select sale.assid 
          from sale 
          where sale.udid = ud.id
     )
 where exists (
      select * 
      from sale 
      where sale.udid = ud.id
 );

MySQL:

update ud u
inner join sale s on
    u.id = s.udid
set u.assid = s.assid

SQL Server:

update u
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid

Oracle:

update
    (select
        u.assid as new_assid,
        s.assid as old_assid
    from ud u
        inner join sale s on
            u.id = s.udid) up
set up.new_assid = up.old_assid

SQLite:

update ud 
     set assid = (
          select sale.assid 
          from sale 
          where sale.udid = ud.id
     )
 where RowID in (
      select RowID 
      from ud 
      where sale.udid = ud.id
 );

Это должно работать в SQL Server:

update ud 
set assid = sale.assid
from sale
where sale.udid = id

postgres

UPDATE table1
SET    COLUMN = value
FROM   table2,
       table3
WHERE  table1.column_id = table2.id
       AND table1.column_id = table3.id
       AND table1.COLUMN = value
       AND table2.COLUMN = value
       AND table3.COLUMN = value 

стандартный подход SQL будет

UPDATE ud
SET assid = (SELECT assid FROM sale s WHERE ud.id=s.id)

на SQL Server вы можете использовать join

UPDATE ud
SET assid = s.assid
FROM ud u
JOIN sale s ON u.id=s.id

PostgreSQL:

CREATE TABLE ud (id integer, assid integer);
CREATE TABLE sales (id integer, udid integer, assid integer);

UPDATE ud
SET assid = sales.assid
FROM sales
WHERE sales.id = ud.id;

упрощенный запрос обновления с помощью вступить - ing несколько таблиц.

   UPDATE
        first_table ft
        JOIN second_table st ON st.some_id = ft.some_id
        JOIN third_table tt  ON tt.some_id = st.some_id
        .....
    SET
        ft.some_column = some_value
    WHERE ft.some_column = 123456 AND st.some_column = 123456

Примечание - first_table, second_table, third_table и some_column как 123456 имена демонстрационных таблиц, имена столбцов и идентификаторы. Замените их действительными именами.


еще один пример, почему SQL на самом деле не переносится.

для MySQL это было бы:

update ud, sale
set ud.assid = sale.assid
where sale.udid = ud.id;

для получения дополнительной информации прочитайте обновление нескольких таблиц: http://dev.mysql.com/doc/refman/5.0/en/update.html

UPDATE [LOW_PRIORITY] [IGNORE] table_references
    SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
    [WHERE where_condition]

Teradata Aster предлагает еще один интересный способ достижения цели:

MERGE INTO ud --what trable should be updated
USING sale -- from what table/relation update info should be taken
ON ud.id = sale.udid --join condition
WHEN MATCHED THEN 
    UPDATE SET ud.assid = sale.assid; -- how to update

Я думал, что SQL-сервер в верхнем посте будет работать для Sybase, так как они оба T-SQL, но, к сожалению, нет.

для Sybase я обнаружил, что обновление должно быть на самой таблице, а не псевдоним:

update ud
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid

следующий оператор с ключевым словом FROM используется для обновления нескольких строк с помощью join

UPDATE users 
set users.DivisionId=divisions.DivisionId
from divisions join users on divisions.Name=users.Division

в MySQL

вы получите лучшую производительность, если забудете предложение where и поместите все условия в выражение ON.

Я думаю, это потому, что запрос сначала должен присоединиться к таблицам, затем запускает предложение where на этом, поэтому, если вы можете уменьшить то, что требуется для присоединения, то это быстрый способ получить результаты/сделать udpate.

пример

сценарий

у вас есть таблица пользователей. Они могут войти, используя свое имя пользователя или email или account_number. Эти учетные записи могут быть активными (1) или неактивными (0). Эта таблица имеет 50000 строк

затем у вас есть таблица пользователей, чтобы отключить на одном дыхании, потому что вы узнаете, что они все сделали что-то плохое. Однако в этой таблице есть один столбец с именами пользователей, электронными письмами и номерами счетов. Он также имеет индикатор "has_run", который должен быть установлен в 1 (true), когда он был запущен

запрос

UPDATE users User
    INNER JOIN
        blacklist_users BlacklistUser
        ON
        (
            User.username = BlacklistUser.account_ref
            OR
            User.email = BlacklistedUser.account_ref
            OR
            User.phone_number = BlacklistUser.account_ref
            AND
            User.is_active = 1
            AND
            BlacklistUser.has_run = 0
        )
    SET
        User.is_active = 0,
        BlacklistUser.has_run = 1;

мышление

Если бы нам пришлось присоединиться только в условиях OR необходимо будет проверить каждую строку 4 раза, чтобы увидеть, следует ли ей присоединиться, и потенциально вернуть намного больше строк. Однако, давая ему больше условий, он может "пропустить" много строк, если они не соответствуют всем условиям при присоединении.

бонус

Это более читабельным. Все условия находятся в одном месте, а строки для обновления-в одном месте


UPDATE tblAppraisalBasicData
SET tblAppraisalBasicData.ISCbo=1
FROM tblAppraisalBasicData SI INNER JOIN  aaa_test RAN ON SI.EmpID = RAN.ID

и в MS ACCESS:

UPDATE ud 
INNER JOIN sale ON ud.id = sale.udid
SET ud.assid = sale.assid;

для SQLite используйте свойство RowID для обновления:

update Table set column = 'NewValue'
where RowID = 
(select t1.RowID from Table t1
join Table t2 fd on t1.JoinField = t2.JoinField
where t2.SelectValue = 'FooMyBarPlease');