¿Cómo puedo hacer una instrucción UPDATE con JOIN in SQL?


Necesito actualizar esta tabla en SQL Server 2005 con los datos de su tabla 'padre', ver a continuación:

Sale

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

Ud

id  (int)
assid  (int)

sale.assid contiene el valor correcto a actualizar ud.assid.

¿Qué consulta hará esto? Estoy pensando en un join pero no estoy seguro de si es posible.

Author: Ronan Boiteau, 2009-08-18

14 answers

La sintaxis depende estrictamente de qué DBMS SQL esté utilizando. Aquí hay algunas maneras de hacerlo en ANSI/ISO (también conocido como debería funcionar en cualquier DBMS SQL), MySQL, SQL Server y Oracle. Tenga en cuenta que mi método ANSI/ISO sugerido normalmente será mucho más lento que los otros dos métodos, pero si está utilizando un DBMS SQL que no sea MySQL, SQL Server u Oracle, entonces puede ser el único camino a seguir (por ejemplo, si su DBMS SQL no admite 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 Servidor:

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

Oráculo:

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
 );
 1990
Author: Eric,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-13 20:14:44

Esto debería funcionar en SQL Server:

update ud 
set assid = sale.assid
from sale
where sale.udid = id
 119
Author: edosoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-31 19:32:50

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 
 84
Author: user1154043,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-09 13:26:21

Un enfoque SQL estándar sería

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

En SQL Server se puede utilizar un join

UPDATE ud
SET assid = s.assid
FROM ud u
JOIN sale s ON u.id=s.id
 39
Author: MattH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-18 12:34:52

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;
 28
Author: alfonx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-08 07:52:18

Consulta de actualización simplificada usando JOIN-ing múltiples tablas.

   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

Nota - first_table, second_table, third_table y some_column como 123456 son nombres de tabla de demostración, nombres de columna e identificadores. Reemplácelos con los nombres válidos.

 18
Author: Vinit Kadkol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-14 07:15:25

Otro ejemplo de por qué SQL no es realmente portable.

Para MySQL sería:

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

Para obtener más información, lea actualización de tabla múltiple: 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]
 11
Author: Yada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-16 19:17:16

Teradata Aster ofrece otra forma interesante de lograr el objetivo:

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
 7
Author: xhudik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-03 10:22:18

Estaba pensando que el SQL-Server uno en el post superior funcionaría para Sybase, ya que ambos son T-SQL, pero desafortunadamente no.

Para Sybase encontré que la actualización debe estar en la propia tabla, no en el alias:

update ud
set u.assid = s.assid
from ud u
    inner join sale s on
        u.id = s.udid
 6
Author: Ken Goh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-19 08:24:18

La siguiente instrucción con la palabra clave FROM se usa para actualizar varias filas con una combinación

UPDATE users 
set users.DivisionId=divisions.DivisionId
from divisions join users on divisions.Name=users.Division
 4
Author: Sheryar Nizar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-06 11:34:28

MySQL

Obtendrá el mejor rendimiento si olvida la cláusula where y coloca todas las condiciones en la expresión ON.

Creo que esto se debe a que la consulta primero tiene que unir las tablas y luego ejecuta la cláusula where en eso, por lo que si puede reducir lo que se requiere para unirse, entonces esa es la forma rápida de obtener los resultados/hacer el udpate.

Ejemplo

Escenario

Tienes una tabla de usuarios. Pueden iniciar sesión usando su nombre de usuario o correo electrónico o número de cuenta. Estas cuentas pueden estar activas (1) o inactivas (0). Esta tabla tiene 50000 filas

Luego tienes una tabla de usuarios para desactivar de una sola vez porque descubres que todos han hecho algo malo. Sin embargo, esta tabla tiene una columna con nombres de usuario, correos electrónicos y números de cuenta mezclados. También tiene un indicador "has_run" que necesita ser establecido en 1 (true) cuando se ha ejecutado

Consulta

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;

Razonamiento

Si tuviéramos que unirnos solo en las condiciones de quirófano, esencialmente necesitaría: compruebe cada fila 4 veces para ver si debe unirse, y potencialmente devolver muchas más filas. Sin embargo, al darle más condiciones, puede "saltar" muchas filas si no cumplen todas las condiciones al unirse.

Bono

Es más legible. Todas las condiciones están en un solo lugar y las filas a actualizar están en un solo lugar

 2
Author: Luke Watts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-09 16:57:54
UPDATE tblAppraisalBasicData
SET tblAppraisalBasicData.ISCbo=1
FROM tblAppraisalBasicData SI INNER JOIN  aaa_test RAN ON SI.EmpID = RAN.ID
 1
Author: Abdullah Yousuf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-19 11:40:06

Y en MS ACCESS:

UPDATE ud 
INNER JOIN sale ON ud.id = sale.udid
SET ud.assid = sale.assid;
 1
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-07 18:38:28

Para SQLite use la propiedad RowID para hacer la actualización:

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');
 0
Author: KeithTheBiped,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-13 14:45:29