Birleştirmeleri kullanarak SQL güncelleme sorgusu


664

3 tablo birleştirme tarafından döndürülen bir değeri olan bir alanı güncelleştirmek zorunda.

Misal:

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

mf_item_numberTablonun alan değerlerini item_masteryukarıdaki koşulda birleştirilen başka bir değerle güncellemek istiyorum .

Bunu MS SQL Server'da nasıl yapabilirim?


124
Lütfen başlamak için bu zımni birleştirmeleri kullanmayı bırakın. Beklenmedik çapraz birleşimler nedeniyle yanlış sonuçlara yol açan zayıf bir tekniktir. Bu kod stili 18 yıldır güncel değil
HLGEM

2
Ayrıca bkz. SO sorusu ... stackoverflow.com/questions/1293330/…
SteveC

Yanıtlar:


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

Açıklığa kavuşturmak için ... UPDATEMadde, FROMmaddede belirtilen tablo takma adına başvurabilir . Yani imbu durumda geçerlidir

Genel örnek

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

9
Postgres şikayet ediyor UPDATE im; im Postgres'in tanımadığı bir takma ad: /
fatuhoku

10
Bilginize bu olacak DEĞİL MySQL (farklı sözdizimi) çalışmak! MySQL için gcbenison'un cevabına bir göz atın
Sliq

67

En kolay yollardan biri, ortak bir tablo ifadesi kullanmaktır (zaten SQL 2005'te olduğunuzdan):

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>

Sorgu yürütme motoru, kaydı nasıl güncelleyeceğini kendi başına çözer.


8
Mükemmel, CTE kullanımı orijinal
SELECT'i

4
SELECT sorgunuzda toplama, DISTINCT vb.
Olmadığı sürece çalışır

1
Genellikle önceki ifadeyi (varsa) sonlandırmak için noktalı virgül ile başlar. CTE kayaları! Karmaşık sorgu / birleştirilmiş güncellemeler tasarlamak basit. Her zaman kullanıyorum ...
Adam W

64

Bunu MySQL'e uyarlamak - bir FROMhüküm yoktur UPDATE, ancak bu işe yarar:

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

Yukarıdaki sql'nizi kullanmadıysanız, ancak bir tabloyu join deyimine göre güncellemeye bir örnek.

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

UPDATE deyiminde "FROM" yan tümcesiyle nasıl ve ne güncelleştirileceğini belirlemede kullanılan ek tablolar belirtebilirsiniz:

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

WHERE yan tümcesinde, bu tabloları birbirine bağlamak için koşulları sağlamanız ve işlemlere katılmanız gerekir.

üzüm posası


5
..ya da FROM yan tümcesinde ANSI
JOINS

5
Evet, ansi birleştirmelerini kullanın, yanlışlıkla bir çapraz birleşiminiz varsa bir güncellemede gerçekten sorun yaşayabilirsiniz.
HLGEM

7

MySQL: Genel olarak, gereksiniminize göre gerekli değişiklikleri yapın:

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

3

Böyle dene ...

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

Aşağıdaki sorguyu kullanabilirsiniz:

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

MERGEKomut ile daha fazla kontrol ile güncelleyebilirsiniz MATCHEDve NOT MATCHED: (Noktayı göstermek için kaynak kodunu biraz değiştirdim)

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.