Zapytanie o aktualizację SQL za pomocą sprzężeń

664

Muszę zaktualizować pole o wartości zwracanej przez połączenie 3 tabel.

Przykład:

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

Chcę zaktualizować mf_item_numberwartości pól tabeli item_mastero inną wartość, która jest połączona w powyższym stanie.

Jak mogę to zrobić w MS SQL Server?

Shyju
źródło
124
Na początek przestań używać tych domniemanych połączeń. Jest to zła technika, która prowadzi do nieprawidłowych wyników z powodu nieoczekiwanych połączeń krzyżowych. Ten styl kodu jest 18 lat nieaktualny
HLGEM
2
Zobacz także SO pytanie ... stackoverflow.com/questions/1293330/
SteveC

Odpowiedzi:

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

Aby to wyjaśnić ... UPDATEKlauzula może odwoływać się do aliasu tabeli określonego w FROMklauzuli. Więc imw tym przypadku jest ważny

Ogólny przykład

UPDATE A
SET foo = B.bar
FROM TableA A
JOIN TableB B
    ON A.col1 = B.colx
WHERE ...
gbn
źródło
9
Postgres narzeka UPDATE im; im jest pseudonimem, którego Postgres nie rozpoznaje: /
fatuhoku,
10
FYI będzie to nie działa w MySQL (inna składnia)! Dla MySQL spójrz na odpowiedź
gcbenison
67

Jednym z najprostszych sposobów jest użycie wspólnego wyrażenia tabelowego (ponieważ korzystasz już z 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>

Mechanizm wykonywania zapytań sam odkryje, jak zaktualizować rekord.

Remus Rusanu
źródło
8
Znakomicie, użycie CTE ułatwia konwersję oryginalnego SELECT na UPDATE
SteveC
4
Działa, dopóki zapytanie SELECT nie zawiera żadnych agregatów, DISTINCT itp.
Baodad
1
Zwykle zaczynam od średnika, aby zakończyć poprzednią instrukcję (jeśli istnieje). Skały CTE! Proste w projektowaniu skomplikowane zapytania / połączone aktualizacje. Używam go cały czas ...
Adam W
64

Dostosowanie tego do MySQL - nie ma FROMklauzuli UPDATE, ale to działa:

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
gcbenison
źródło
12

Nie użyłem twojej sql powyżej, ale oto przykład aktualizacji tabeli na podstawie instrukcji 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%'
Przyjemny
źródło
8

Możesz określić dodatkowe tabele używane do określania sposobu i sposobu aktualizacji za pomocą klauzuli „FROM” w instrukcji UPDATE, jak poniżej:

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

W klauzuli WHERE należy podać warunki i połączyć operacje, aby połączyć te tabele razem.

Marc

marc_s
źródło
5
... lub użyj ANSI JOINS w klauzuli FROM
gbn
5
Tak, skorzystaj z połączeń ansi, możesz mieć poważne problemy z aktualizacją, jeśli przypadkowo dostaniesz połączenie krzyżowe.
HLGEM,
7

MySQL: Zasadniczo wprowadź niezbędne zmiany zgodnie ze swoimi wymaganiami:

UPDATE
    shopping_cart sc
    LEFT JOIN
    package pc ON sc. package_id = pc.id    
SET
    sc. amount = pc.amount
Vinod Joshi
źródło
3

Spróbuj tak ...

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;
Ankitkumar Tandel
źródło
2

Możesz użyć następującego zapytania:

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`
Prasan Karunarathna
źródło
1

Możesz aktualizować za pomocą MERGECommand ze znacznie większą kontrolą MATCHEDi NOT MATCHED: (nieznacznie zmieniłem kod źródłowy, aby zademonstrować swój punkt)

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
Yashar Aliabbasi
źródło