Query di aggiornamento SQL tramite join


664

Devo aggiornare un campo con un valore che viene restituito da un join di 3 tabelle.

Esempio:

select
    im.itemid
    ,im.sku as iSku
    ,gm.SKU as GSKU
    ,mm.ManufacturerId as ManuId
    ,mm.ManufacturerName
    ,im.mf_item_number
    ,mm.ManufacturerID
from 
    item_master im, group_master gm, Manufacturer_Master mm 
where
    im.mf_item_number like 'STA%'
    and im.sku=gm.sku
    and gm.ManufacturerID = mm.ManufacturerID
    and gm.manufacturerID=34

Voglio aggiornare i mf_item_numbervalori di campo della tabella item_mastercon qualche altro valore che è unito nella condizione sopra.

Come posso farlo in MS SQL Server?


124
Si prega di smettere di usare quei join impliciti per cominciare. È una tecnica scadente che porta a risultati errati a causa di join incrociati imprevisti. Questo stile di codice è obsoleto di 18 anni
HLGEM

2
Vedi anche domanda SO ... stackoverflow.com/questions/1293330/...
SteveC

Risposte:


1251
UPDATE im
SET mf_item_number = gm.SKU --etc
FROM item_master im
JOIN group_master gm
    ON im.sku = gm.sku 
JOIN Manufacturer_Master mm
    ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
      gm.manufacturerID = 34

Per chiarire ... La UPDATEclausola può fare riferimento a un alias di tabella specificato nella FROMclausola. Quindi imin questo caso è valido

Esempio generico

UPDATE A
SET foo = B.bar
FROM TableA A
JOIN TableB B
    ON A.col1 = B.colx
WHERE ...

9
Postgres si lamenta UPDATE im; im è un alias che Postgres non riconosce: /
fatuhoku il

10
FYI questo non funzionerà in MySQL (sintassi diversa)! Per MySQL dai un'occhiata alla risposta di
gcbenison

67

Uno dei modi più semplici è utilizzare un'espressione di tabella comune (dal momento che sei già su SQL 2005):

with cte as (
select
    im.itemid
    ,im.sku as iSku
    ,gm.SKU as GSKU
    ,mm.ManufacturerId as ManuId
    ,mm.ManufacturerName
    ,im.mf_item_number
    ,mm.ManufacturerID
    , <your other field>
from 
    item_master im, group_master gm, Manufacturer_Master mm 
where
    im.mf_item_number like 'STA%'
    and im.sku=gm.sku
    and gm.ManufacturerID = mm.ManufacturerID
    and gm.manufacturerID=34)
update cte set mf_item_number = <your other field>

Il motore di esecuzione della query scoprirà da solo come aggiornare il record.


8
Eccellente, l'uso del CTE semplifica la conversione dell'originale SELECT in un AGGIORNAMENTO
SteveC

4
Funziona finché la query SELECT non contiene aggregati, DISTINCT, ecc.
Baodad,

1
Di solito inizio con un punto e virgola per terminare la precedente dichiarazione (se presente). Rocce CTE! Semplici da progettare complicati query / aggiornamenti uniti Lo uso sempre ...
Adam W,

64

Adattandolo a MySQL - non esiste alcuna FROMclausola UPDATE, ma funziona:

UPDATE
    item_master im
    JOIN
    group_master gm ON im.sku=gm.sku 
    JOIN
    Manufacturer_Master mm ON gm.ManufacturerID=mm.ManufacturerID
SET
    im.mf_item_number = gm.SKU --etc
WHERE
    im.mf_item_number like 'STA%'
    AND
    gm.manufacturerID=34

12

Non hai usato il tuo sql sopra ma ecco un esempio di aggiornamento di una tabella basata su un'istruzione join.

UPDATE p
SET    p.category = c.category
FROM   products p
       INNER JOIN prodductcatagories pg
            ON  p.productid = pg.productid
       INNER JOIN categories c
            ON  pg.categoryid = c.cateogryid
WHERE  c.categories LIKE 'whole%'

8

È possibile specificare ulteriori tabelle utilizzate per determinare come e cosa aggiornare con la clausola "FROM" nell'istruzione UPDATE, in questo modo:

update item_master
set mf_item_number = (some value)
from 
   group_master as gm
   join Manufacturar_Master as mm ON ........
where
 .... (your conditions here)

Nella clausola WHERE, è necessario fornire le condizioni e unire le operazioni per associare queste tabelle.

Marc


5
..o usare ANSI JOINS nella clausola FROM
gbn

5
Sì, utilizza i join ansi, potresti avere dei problemi in un aggiornamento se accidentalmente ricevi un cross join.
HLGEM,

7

MySQL: in generale, apporta le modifiche necessarie in base alle tue esigenze:

UPDATE
    shopping_cart sc
    LEFT JOIN
    package pc ON sc. package_id = pc.id    
SET
    sc. amount = pc.amount

3

Prova così ...

Update t1.Column1 = value 
from tbltemp as t1 
inner join tblUser as t2 on t2.ID = t1.UserID 
where t1.[column1]=value and t2.[Column1] = value;

2

È possibile utilizzare la seguente query:

UPDATE im
SET mf_item_number = (some value) 
FROM item_master im
JOIN group_master gm
    ON im.sku = gm.sku 
JOIN Manufacturer_Master mm
    ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
      gm.manufacturerID = 34    `sql`

1

Puoi aggiornare con MERGECommand con un controllo molto maggiore MATCHEDe NOT MATCHED: (Ho leggermente modificato il codice sorgente per dimostrare il mio punto)

USE tempdb;
GO
IF(OBJECT_ID('target') > 0)DROP TABLE dbo.target
IF(OBJECT_ID('source') > 0)DROP TABLE dbo.source
CREATE TABLE dbo.Target
    (
      EmployeeID INT ,
      EmployeeName VARCHAR(100) ,
      CONSTRAINT Target_PK PRIMARY KEY ( EmployeeID )
    );
CREATE TABLE dbo.Source
    (
      EmployeeID INT ,
      EmployeeName VARCHAR(100) ,
      CONSTRAINT Source_PK PRIMARY KEY ( EmployeeID )
    );
GO
INSERT  dbo.Target
        ( EmployeeID, EmployeeName )
VALUES  ( 100, 'Mary' );
INSERT  dbo.Target
        ( EmployeeID, EmployeeName )
VALUES  ( 101, 'Sara' );
INSERT  dbo.Target
        ( EmployeeID, EmployeeName )
VALUES  ( 102, 'Stefano' );

GO
INSERT  dbo.Source
        ( EmployeeID, EmployeeName )
VALUES  ( 100, 'Bob' );
INSERT  dbo.Source
        ( EmployeeID, EmployeeName )
VALUES  ( 104, 'Steve' );
GO

SELECT * FROM dbo.Source
SELECT * FROM dbo.Target

MERGE Target AS T
USING Source AS S
ON ( T.EmployeeID = S.EmployeeID )
WHEN MATCHED THEN
    UPDATE SET T.EmployeeName = S.EmployeeName + '[Updated]';
GO 
SELECT '-------After Merge----------'
SELECT * FROM dbo.Source
SELECT * FROM dbo.Target
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.