web-dev-qa-db-fra.com

Mise à jour de SQL Server avec jointure interne

J'ai 3 tableaux (simplifiés):

 tblOrder(OrderId INT)  
  tblVariety(VarietyId INT,Stock INT)  
  tblOrderItem(OrderId,VarietyId,Quantity INT)

Si je passe une commande, je baisse le niveau de stock en utilisant ceci:

UPDATE tblVariety  
SET tblVariety.Stock = tblVariety.Stock - tblOrderItem.Quantity  
FROM tblVariety  
INNER JOIN tblOrderItem ON tblVariety.VarietyId = tblOrderItem.VarietyId  
INNER JOIN tblOrder ON tblOrderItem.OrderId = tblOrder.OrderId  
WHERE tblOrder.OrderId = 1

Très bien, jusqu'à ce qu'il y ait deux lignes dans tblOrderItem avec le même VarietyId pour le même OrderId. Dans ce cas, une seule des lignes est utilisée pour la mise à jour du stock. Il semble être en train de faire un GROUP BY VarietyId.

Quelqu'un peut-il nous éclairer? Merci beaucoup.

25
Geoff

Je suppose que parce que vous nous avez montré un schéma simplifié, certaines informations manquent qui détermineraient pourquoi les valeurs VarietyID répétées pour un OrderID donné.

Lorsque vous avez plusieurs lignes, SQL Server sélectionne arbitrairement l'une d'entre elles pour la mise à jour.

Si tel est le cas, vous devez d'abord grouper

UPDATE V
SET
   Stock = Stock - foo.SumQuantity
FROM
    tblVariety V
    JOIN
    (SELECT SUM(Quantity) AS SumQuantity, VarietyID
     FROM tblOrderItem
      JOIN tblOrder ON tblOrderItem.OrderId = tblOrder.OrderId  
     WHERE tblOrder.OrderId = 1
     GROUP BY VarietyID
    ) foo ON V.VarietyId = foo.VarietyId  

Si ce n'est pas le cas, la table OrderItems PK est erronée car si elle autorise les combinaisons OrderID/VarietyID en double (la PK doit être OrderID/VarietyID, ou celles-ci doivent être contraintes comme uniques)

43
gbn

À partir de la documentation UPDATE

Les résultats d'une instruction UPDATE ne sont pas définis si l'instruction inclut une clause FROM qui n'est pas spécifiée de telle sorte qu'une seule valeur est disponible pour chaque occurrence de colonne mise à jour (en d'autres termes, si l'instruction UPDATE n'est pas déterministe). Par exemple, étant donné l'instruction UPDATE dans le script suivant, les deux lignes de la table s répondent aux qualifications de la clause FROM dans l'instruction UPDATE, mais c'est indéfini quelle ligne de s est utilisée pour mettre à jour la ligne du tableau t.

CREATE TABLE s (ColA INT, ColB DECIMAL(10,3))
GO
CREATE TABLE t (ColA INT PRIMARY KEY, ColB DECIMAL(10,3))
GO
INSERT INTO s VALUES(1, 10.0)
INSERT INTO s VALUES(1, 20.0)
INSERT INTO t VALUES(1, 0.0)
GO
UPDATE t 
SET t.ColB = t.ColB + s.ColB
FROM t INNER JOIN s ON (t.ColA = s.ColA)
GO
12
Adriaan Stander

Vous faites une mise à jour. Il sera mis à jour une fois.

Modifier: pour résoudre, vous pouvez ajouter une sous-requête qui regroupera vos articles de commande par ordre et variété, avec une somme sur le montant.

1
Tobiasopdenbrouw