Вопрос по stored-procedures, sql-server, sql-update, sql – SQL Update несколько полей FROM с помощью инструкции SELECT

36

Это работает, но я хотел бы удалить избыточность. Есть ли способ объединить обновление с одним оператором select, поэтому мне не нужно использовать 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 
        [email protected]

    UPDATE SHIPMENT
    SET
        OrgAddress1     =   @OrgAddress1,
        OrgAddress2     =   @OrgAddress2,
        OrgCity         =   @OrgCity,
        OrgState        =   @OrgState,
        OrgZip          =   @OrgZip,
        DestAddress1    =   @DestAddress1,
        DestAddress2    =   @DestAddress2,
        DestCity        =   @DestCity,
        DestState       =   @DestState,
        DestZip         =   @DestZip
    WHERE 
        [email protected] MyID2

Ваш Ответ

6   ответов
1

что-то вроде:

обновить комплект поставки .... от отгрузка внутреннее соединение ProfilerTest.dbo.BookingDetails на ...

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 [email protected]
) q
WHERE [email protected] MyID2
54

о памяти):

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

Это помогает?

К вашему сведению - это не работает в оракуле. Вместо этого вы можете использовать & lt; code & gt; обновить (выберите table1.field1 как a1, table2.field2 как b1 из table1, table2, где field1 = field2) установите a1 = b1 примечание: я думаю, что псевдонимы необходимы, если ваши поля имеют одно и то же имя по какой-то причине.
работает как шарм, я знал, что должен быть способ сделать обновление, основанное на утверждении select, но как меня ускользнуло. Christopher Kelly
@Jody: вопрос касался SQL Server, а не Oracle, поэтому я дал решение, которое работает в SQL Server.
@IbrahimOudah Ответ сказал мне, что делать, и комментарий Джоди, почему я раньше не видел этот синтаксис
@marc_s НО ХОРОШО ОТ ДЖОДДЫ, ЧТО ОН ОБЕСПЕЧИВАЕТ ДРУГИХ О ORACLE.
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 s SET читатьSELECT! Затем вы увидите эти данные такими, какими они будут, если бы обновление имело место.

Что ж, возник вопрос о том, зачем указывать Отгрузку в предложении FROM, а не после обновления. Ответ marc_s выше, и это фактически тот же план выполнения в MSSQL
Такая же разница. Это чище для меня. Я не выбираю дважды. Я получаю только результаты от s, как от предложения FROM.
0

когда я добавил порядковый номер (чтобы элементы, сгруппированные по родительскому идентификатору, имели последовательность, по которой я могу упорядочить (и, вероятно, пользователь может изменить порядковый номер, чтобы изменить порядок).

В моем случае это страховка для пациента, и пользователь получает возможность установить назначенный им порядок, поэтому простой переход по первичному ключу не полезен для долгосрочного использования, но полезен для установки значения по умолчанию.

Проблема со всеми остальными решениями заключается в том, что определенные агрегатные функции не разрешены вне 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 

это позволяет мне выбрать идентификатор, который мне нужен, и значение, которое нужно установить для этого идентификатора. Другие решения были бы хорошими, если бы я не использовал Row_Number (), который не будет работать вне SELECT.

Учитывая, что это однократная операция, ее кодирование все еще простое, и скорость выполнения достаточно высока для 4000+ строк.

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 

Таким образом, объединение является явным, поскольку неявные объединения являются ИМХО плохой вещью. Вы можете запустить закомментированный выбор (обычно я указываю поля, в которых я обновляю старые и новые значения рядом друг с другом), чтобы убедиться, что то, что я собираюсь обновить, именно то, что я хотел обновить.

Даже не заметил, что, возможно, перекрестное соединение - лучшее решение. Только ОП знает наверняка.
Я не уверен, учитывая, что в исходном примере существует отношение один к одному (или много) между BookingDetails и Отправкой для bd.MyID к s.MyID2. В приведенном примере (допустим, я предполагаю) два разных параметра для идентификаторов, поэтому я предполагаю, что они могут быть разными. Я согласен с тем, что если существует явное соединение, его следует использовать!

Похожие вопросы