SQL met à jour plusieurs champs à partir d'une instruction SELECT
Cela fonctionne, mais je voudrais supprimer la redondance. Existe-t-il un moyen de fusionner la mise à jour avec une seule instruction select, donc je n'ai pas besoin d'utiliser vars?
DECLARE
@OrgAddress1 varchar,
@OrgAddress2 varchar,
@OrgCity varchar,
@OrgState varchar,
@OrgZip varchar,
@DestAddress1 varchar,
@DestAddress2 varchar,
@DestCity varchar,
@DestState varchar,
@DestZip varchar
SELECT
@OrgAddress1 = OrgAddress,
@OrgAddress2 = OrgAddress2,
@OrgCity = OrgCity,
@OrgState = OrgState,
@OrgZip = OrgZip,
@DestAddress1 = DestAddress,
@DestAddress2 = DestAddress2,
@DestCity = DestCity,
@DestState = DestState,
@DestZip = DestZip
FROM
ProfilerTest.dbo.BookingDetails
WHERE
MyID=@MyID
UPDATE SHIPMENT
SET
OrgAddress1 = @OrgAddress1,
OrgAddress2 = @OrgAddress2,
OrgCity = @OrgCity,
OrgState = @OrgState,
OrgZip = @OrgZip,
DestAddress1 = @DestAddress1,
DestAddress2 = @DestAddress2,
DestCity = @DestCity,
DestState = @DestState,
DestZip = @DestZip
WHERE
MyID2=@ MyID2
6 réponses
Quelque chose comme ça devrait fonctionner (ne peut pas le tester en ce moment-de la mémoire):
UPDATE SHIPMENT
SET
OrgAddress1 = BD.OrgAddress1,
OrgAddress2 = BD.OrgAddress2,
OrgCity = BD.OrgCity,
OrgState = BD.OrgState,
OrgZip = BD.OrgZip,
DestAddress1 = BD.DestAddress1,
DestAddress2 = BD.DestAddress2,
DestCity = BD.DestCity,
DestState = BD.DestState,
DestZip = BD.DestZip
FROM
BookingDetails BD
WHERE
SHIPMENT.MyID2 = @MyID2
AND
BD.MyID = @MyID
Est-ce que c'?
Vous devriez être capable de faire quelque chose dans le sens de ce qui suit
UPDATE s
SET
OrgAddress1 = bd.OrgAddress1,
OrgAddress2 = bd.OrgAddress2,
...
DestZip = bd.DestZip
FROM
Shipment s, ProfilerTest.dbo.BookingDetails bd
WHERE
bd.MyID = @MyId AND s.MyID2 = @MyID2
FROM statement peut être rendu plus optimial (en utilisant des jointures plus spécifiques), mais ce qui précède devrait faire l'affaire. Aussi, un bon avantage de côté à l'écrire de cette façon, pour voir un aperçu de la mise à jour change UPDATE s SET
à lire SELECT
! Vous verrez alors ces données telles qu'elles apparaîtraient si la mise à jour avait eu lieu.
Vous pouvez utiliser:
UPDATE s SET
s.Field1 = q.Field1,
s.Field2 = q.Field2,
(list of fields...)
FROM (
SELECT Field1, Field2, (list of fields...)
FROM ProfilerTest.dbo.BookingDetails
WHERE MyID=@MyID
) q
WHERE s.MyID2=@ MyID2
Je l'écrirais de cette façon
UPDATE s
SET OrgAddress1 = bd.OrgAddress1, OrgAddress2 = bd.OrgAddress2,
... DestZip = bd.DestZip
--select s.OrgAddress1, bd.OrgAddress1, s.OrgAddress2, bd.OrgAddress2, etc
FROM Shipment s
JOIN ProfilerTest.dbo.BookingDetails bd on bd.MyID =s.MyID2
WHERE bd.MyID = @MyId
De cette façon, la jointure est explicite car les jointures implicites sont une mauvaise chose à mon humble avis. Vous pouvez exécuter la sélection commentée (généralement je spécifie les champs que je mets à jour les anciennes et les nouvelles valeurs les unes à côté des autres) pour vous assurer que ce que je vais mettre à jour est exactement ce que je voulais mettre à jour.
J'ai juste dû résoudre un problème similaire où j'ai ajouté un numéro de séquence (de sorte que les éléments regroupés par un ID parent, ont une séquence que je peux commander (et vraisemblablement l'utilisateur peut changer le numéro de séquence pour changer l'ordre).
Dans mon cas, c'est une assurance pour un Patient, et l'utilisateur peut définir l'ordre dans lequel il est assigné, donc passer par la clé primaire n'est pas utile à long terme, mais est utile pour définir une valeur par défaut.
Le problème avec toutes les autres solutions que certaines fonctions d'agrégat ne sont pas autorisées en dehors D'un SELECT
Cette sélection vous donne le nouveau numéro de Séquence:
select PatientID,
PatientInsuranceID,
Sequence,
Row_Number() over(partition by PatientID order by PatientInsuranceID) as RowNum
from PatientInsurance
order by PatientID, PatientInsuranceID
Cette commande de mise à jour, serait simple, mais n'est pas autorisée:
update PatientInsurance
set Sequence = Row_Number() over(partition by PatientID order by PatientInsuranceID)
La solution qui a fonctionné (je viens de le faire), et est similaire à la solution d'eKek0:
UPDATE PatientInsurance
SET PatientInsurance.Sequence = q.RowNum
FROM (select PatientInsuranceID,
Row_Number() over(partition by PatientID order by PatientInsuranceID) as RowNum
from PatientInsurance
) as q
WHERE PatientInsurance.PatientInsuranceID=q.PatientInsuranceID
Cela me permet de sélectionner l'ID dont j'ai besoin pour correspondre aux choses, et la valeur que je dois définir pour cet ID. D'autres solutions auraient été bien si je n'utilisais pas Row_Number () qui ne fonctionnera pas en dehors d'un SELECT.
Étant donné qu'il s'agit d'une opération 1 fois, le codage est toujours simple, et la vitesse d'exécution est assez rapide pour plus de 4000 lignes