SQL-Update-Abfrage mithilfe von Joins


663

Ich muss ein Feld mit einem Wert aktualisieren, der durch einen Join von 3 Tabellen zurückgegeben wird.

Beispiel:

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

Ich möchte die mf_item_numberFeldwerte der Tabelle item_mastermit einem anderen Wert aktualisieren, der in der obigen Bedingung verbunden ist.

Wie kann ich das in MS SQL Server tun?


124
Bitte hören Sie zunächst auf, diese implizierten Verknüpfungen zu verwenden. Es ist eine schlechte Technik, die aufgrund unerwarteter Querverbindungen zu falschen Ergebnissen führt. Dieser
Codestil

Antworten:


1250
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

Zur Verdeutlichung ... Die UPDATEKlausel kann auf einen in der FROMKlausel angegebenen Tabellenalias verweisen . Also imin diesem Fall gilt ,

Allgemeines Beispiel

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

9
Postgres beschwert sich über UPDATE im;
Ich bin

10
Zu Ihrer Information, dies wird NICHT in MySQL funktionieren (andere Syntax)! Für MySQL werfen Sie einen Blick auf die Antwort von
gcbenison

67

Eine der einfachsten Möglichkeiten ist die Verwendung eines allgemeinen Tabellenausdrucks (da Sie bereits mit SQL 2005 arbeiten):

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>

Die Abfrageausführungs-Engine wird selbst herausfinden, wie der Datensatz aktualisiert wird.


8
Hervorragend, die Verwendung des CTE macht es einfach, das ursprüngliche SELECT in ein UPDATE
umzuwandeln

4
Funktioniert, solange Ihre SELECT-Abfrage keine Aggregate, DISTINCT usw. enthält.
Baodad

1
Normalerweise beginne ich mit einem Semikolon, um die vorherige Anweisung (falls vorhanden) zu beenden. CTE rockt! Einfach zu entwerfende komplizierte Abfragen / verbundene Updates. Ich benutze es die ganze Zeit ...
Adam W

64

Anpassung an MySQL - es gibt keine FROMKlausel UPDATE, aber das funktioniert:

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

Ich habe Ihr SQL oben nicht verwendet, aber hier ist ein Beispiel für die Aktualisierung einer Tabelle basierend auf einer Join-Anweisung.

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

Sie können zusätzliche Tabellen angeben, anhand derer bestimmt wird, wie und was mit der FROM-Klausel in der UPDATE-Anweisung aktualisiert werden soll:

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

In der WHERE-Klausel müssen Sie die Bedingungen und Verknüpfungsoperationen angeben, um diese Tabellen miteinander zu verbinden.

Marc


5
..oder verwenden Sie ANSI JOINS in der FROM-Klausel
gbn

5
Ja, bitte verwenden Sie die Ansi-Joins. Sie könnten bei einem Update echte Probleme haben, wenn Sie versehentlich einen Cross-Join erhalten haben.
HLGEM

7

MySQL: Nehmen Sie im Allgemeinen die erforderlichen Änderungen an Ihren Anforderungen vor:

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

3

Versuchen Sie es so ...

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

Sie können die folgende Abfrage verwenden:

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

Sie können mit MERGECommand mit viel mehr Kontrolle über MATCHEDund aktualisieren NOT MATCHED: (Ich habe den Quellcode leicht geändert, um meinen Standpunkt zu demonstrieren.)

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.