Запрос на обновление SQL с использованием соединений


664

Я должен обновить поле со значением, которое возвращается объединением 3 таблиц.

Пример:

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_numberзначения полей таблицы item_masterдругим значением, которое объединено в вышеуказанном условии.

Как я могу сделать это в MS SQL Server?


124
Пожалуйста, прекратите использовать эти подразумеваемые объединения для начала. Это плохая техника, которая приводит к неверным результатам из-за неожиданных перекрестных соединений. Этот стиль кода устарел на 18 лет
HLGEM

2
Смотрите также ТАК вопрос ... stackoverflow.com/questions/1293330/…
SteveC

Ответы:


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

Чтобы было понятно ... Предложение UPDATEможет ссылаться на псевдоним таблицы, указанный в FROMпредложении. Так что imв этом случае действует

Общий пример

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

9
Постгрес жалуется UPDATE im; Это псевдоним, который Postgres не распознает: /
fatuhoku

10
К вашему сведению, это НЕ будет работать в MySQL (другой синтаксис)! Для MySQL посмотрите на ответ
gcbenison

67

Один из самых простых способов - использовать общее табличное выражение (поскольку вы уже используете 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>

Механизм выполнения запросов самостоятельно выяснит, как обновить запись.


8
Отлично, использование CTE упрощает преобразование оригинального SELECT в ОБНОВЛЕНИЕ
SteveC

4
Работает до тех пор, пока ваш запрос SELECT не имеет никаких агрегатов, DISTINCT и т. Д.
Baodad

1
Я обычно начинаю с точки с запятой, чтобы завершить предыдущее утверждение (если оно есть). CTE качается! Простой дизайн сложных запросов / обновлений. Я использую это все время ...
Адам W

64

Адаптируя это к MySQL - здесь нет FROMпредложения UPDATE, но это работает:

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

Вы не использовали ваш sql выше, но вот пример обновления таблицы на основе оператора соединения.

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

Вы можете указать дополнительные таблицы, используемые при определении того, как и что обновлять, с помощью предложения «FROM» в выражении UPDATE, например:

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 необходимо указать условия и операции соединения, чтобы связать эти таблицы вместе.

Марк


5
..или использовать ANSI JOINS в предложении FROM
gbn

5
Да, пожалуйста, используйте ANSI-соединения, вы можете столкнуться с серьезными проблемами при обновлении, если случайно получили перекрестное соединение.
HLGEM

7

MySQL: В общем, внесите необходимые изменения в соответствии с вашими требованиями:

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


2

Вы можете использовать следующий запрос:

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

Вы можете обновить с помощью MERGECommand с гораздо большим контролем MATCHEDи NOT MATCHED: (Я немного изменил исходный код, чтобы продемонстрировать свою точку зрения)

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.