SQL通过SELECT语句更新多个字段FROM

时间:2009-08-12 18:45:54

标签: sql sql-server stored-procedures sql-update

这有效,但我想删除冗余。 有没有办法将更新与单个select语句合并,所以我不必使用变量?

    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 个答案:

答案 0 :(得分:55)

这样的事情应该有效(现在无法从内存中测试):

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

这有帮助吗?

答案 1 :(得分:6)

您应该可以按照以下方式执行某些操作

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语句可以更加优化(使用更具体的连接),但上面应该可以做到。另外,以这种方式编写它会带来很好的好处,看看UPDATE更改UPDATE s SET的预览,以便阅读SELECT!然后,您将看到在更新发生时显示的数据。

答案 2 :(得分:5)

您可以使用:

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

答案 3 :(得分:1)

您可以使用来自...的更新

类似的东西:

更新货件集.... 从 装船 内部联接ProfilerTest.dbo.BookingDetails on ...

答案 4 :(得分:0)

我会这样写的

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 

这种方式连接是显式的,因为隐式连接是一件坏事恕我直言。您可以运行注释掉的选择(通常我指定我正在更新彼此相邻的旧值和新值的字段),以确保我要更新的内容正是我要更新的内容。

答案 5 :(得分:0)

我只需要解决一个类似的问题,我添加了一个序列号(以便按父ID分组的项目有一个我可以订购的序列(并且可能是用户可以更改序列号来改变排序) )。

在我的情况下,它对患者来说是保险,并且用户可以设置他们被分配的顺序,因此仅使用主键对于长期来说没有用,但是对于设置默认值很有用。

所有其他解决方案的问题是某些聚合函数不允许在SELECT

之外

此SELECT为您提供新的序列号:

select PatientID,
       PatientInsuranceID, 
       Sequence, 
       Row_Number() over(partition by PatientID order by PatientInsuranceID) as RowNum
from PatientInsurance
order by PatientID, PatientInsuranceID

此更新命令很简单,但不允许:

update PatientInsurance
set Sequence = Row_Number() over(partition by PatientID order by PatientInsuranceID)

有效的解决方案(我刚做过),与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 

这让我可以选择我需要匹配的ID,以及我需要为该ID设置的值。如果我没有使用Row_Number(),那么其他解决方案就没问题了。这不会在SELECT之外工作。

鉴于这是一次操作,它的编码仍然很简单,运行速度足够快4000+行