Як оновити дві таблиці в одному операторі в SQL Server 2005?


193

Я хочу оновити дві таблиці за один раз. Як це зробити в SQL Server 2005?

UPDATE 
  Table1, 
  Table2
SET 
  Table1.LastName='DR. XXXXXX', 
  Table2.WAprrs='start,stop'
FROM 
  Table1 T1, 
  Table2 T2
WHERE 
  T1.id = T2.id
AND 
  T1.id = '010008'

4
Це допоможе, якби ви пояснили, чому.
Ерік Мікельсен

2
Боюся, SQL сервер 2005 не підтримує оновлення декількох таблиць в одному запиті.
Пранав Сінгх

Відповіді:


195

Ви не можете оновити кілька таблиць в одному операторі, проте ви можете скористатися транзакцією, щоб переконатися, що два UPDATEоператори обробляються атомно. Ви також можете замовити їх, щоб уникнути туди і назад.

BEGIN TRANSACTION;

UPDATE Table1
  SET Table1.LastName = 'DR. XXXXXX' 
FROM Table1 T1, Table2 T2
WHERE T1.id = T2.id
and T1.id = '011008';

UPDATE Table2
SET Table2.WAprrs = 'start,stop'
FROM Table1 T1, Table2 T2
WHERE T1.id = T2.id
and T1.id = '011008';

COMMIT;

Насправді я оновлюю записи цих двох таблиць з іншої спокусливої. temptable має посилання на table1, але не table2. Як я можу оновити той самий запис таблиці2? Як я зв’яжу це?
Jango

@unknown: Виходячи з вашого коментаря, вам потрібно буде приєднатись як до Table1, так і до Table2 під час оновлення Table2, якщо для запиту на оновлення потрібні ключі з третьої таблиці. Незалежно від цього, вам все одно потрібно зробити два окремих оновлення.
Л.Бушкін

3
Мабуть, не пов’язано: це не працюватиме на MYSQL, оскільки синтаксис оновлення для mysql відрізняється. вам доведеться перейти ОНОВЛЕННЯ Таблиця1, Таблиця2 SET Таблиця1.LastName = 'DR. XXXXXX 'ДЕ T1.id = T2.id
Хуан Вілар

чи потрібно нам підтримувати зв’язок первинного ключа та зовнішнього ключа між ними
srinivas gowda

2
Ви також повинні помістити свої повідомлення про оновлення всередині блоку try / catch, щоб уникнути часткового оновлення у разі помилки. дивіться це запитання: stackoverflow.com/questions/1749719/…
mechatroner

84

Ви не можете оновити дві таблиці відразу, але ви можете зв'язати оновлення у вкладиші OUTPUT INTO, використовуючи цей вихід, як з'єднання для другого оновлення:

DECLARE @ids TABLE (id int);
BEGIN TRANSACTION

UPDATE Table1 
SET Table1.LastName = 'DR. XXXXXX'  
OUTPUT INSERTED.id INTO @ids
WHERE Table1.field = '010008';

UPDATE Table2 
SET Table2.WAprrs = 'start,stop' 
FROM Table2 
JOIN @ids i on i.id = Table2.id;

COMMIT;

Я змінив вашу WHEREумову прикладу, щоб бути якимось іншим полем id. Якщо це idвам не потрібна ця фантазія OUTPUT, ви можете просто UPDATEдругу таблицю для того ж id='010008'.


Це найкраща відповідь, і її слід вважати справжньою відповіддю на початкове запитання. Дякую. Це працювало для мене.
Fandango68

1
Це T1.fieldмає бути Table1.field?
WAF

22

Вибачте, afaik, ви не можете цього зробити. Для оновлення атрибутів у двох різних таблицях вам потрібно буде виконати два окремі оператори. Але вони можуть бути в пакеті (набір SQL, що надсилається серверу за одну туру)


2
Огонь! Мені слід частіше використовувати слово Вибачення для зайвих кудосів: P
Fandango68,

14

Коротка відповідь на це - ні. Хоча ви можете вводити декілька таблиць у fromпункті оператора оновлення, ви можете вказати одну таблицю лише після updateключового слова. Навіть якщо ви пишете "оновлений" перегляд (який просто перегляд, який відповідає певним обмеженням), такі оновлення не вдасться. Ось відповідні кліпи з документації MSDN (акцент - мій).

ОНОВЛЕННЯ (Transact-SQL)

Подання, на яке посилається ім'я table_or_view_name, повинно бути оновлене та посилатися саме на одну базову таблицю в пункті FROM подання. Щоб отримати додаткові відомості про оновлення представлень, див. СТВОРИТИ ВИДИ (Transact-SQL).

СТВОРИТИ ПОГЛЯД (Transact-SQL)

Ви можете змінювати дані базової базової таблиці за допомогою перегляду, якщо виконуються наступні умови:

  • Будь-які зміни, включаючи заяви UPDATE, INSERT та DELETE, повинні посилатися на стовпці лише з однієї базової таблиці .
  • Стовпці, що модифікуються у представленні даних, повинні безпосередньо посилатися на базові дані у стовпцях таблиці. Стовпці неможливо отримати жодним іншим способом, наприклад, за допомогою наступного:
    • Сукупна функція: AVG, COUNT, SUM, MIN, MAX, GROUPING, STDEV, STDEVP, VAR і VARP.
    • Обчислення. Стовпець не можна обчислити з виразу, який використовує інші стовпці. Стовпці, сформовані за допомогою встановлених операторів UNION, UNION ALL, CROSSJOIN, EXCEPT та INTERSECT, складають обчислення і також не підлягають оновленню.
  • Сплани GROUP BY, HAVING або DISTINCT на змінені стовпці не впливають.
  • TOP не використовується ніде в select_statement подання разом із пунктом "ЗАВЕРШИТИ ОПЦІЮ".

Чесно кажучи, вам слід розглянути можливість використання двох різних операторів SQL в рамках транзакції, як на прикладі Л.Бушкіна.

ОНОВЛЕННЯ: Моє оригінальне твердження, що ви можете оновити кілька таблиць у оновленому вигляді, було помилковим. У SQL Server 2005 та 2012 році вона призведе до наступної помилки. Я виправив свою відповідь, щоб відобразити це.

Msg 4405, Level 16, State 1, Line 1

View or function 'updatable_view' is not updatable because the modification affects multiple base tables.


1
Хоча неможливо оновити об’єкт View, який впливатиме на декілька таблиць, ви можете створити тригери INSTEAD OF, які розбивають оригінал на окремі оператори (зачіпаючи кожну таблицю):INSTEAD OF Specifies that the DML trigger is executed instead of the triggering SQL statement, therefore, overriding the actions of the triggering statements. INSTEAD OF cannot be specified for DDL or logon triggers.
4:00

9

Це працює для MySQL і насправді є лише неявною транзакцією, але вона повинна мати щось подібне:

UPDATE Table1 t1, Table2 t2 SET 
t2.field = t2.field+2,
t1.field = t1.field+2

WHERE t1.id = t2.foreign_id and t2.id = '123414'

якщо ви робите оновлення для декількох таблиць, для яких потрібні кілька операцій…, що, ймовірно, можливо, якщо ви оновите одну, то іншу, виходячи з інших умов…, вам слід використовувати транзакцію. 


1
Цей ансер все ще актуальний для інших користувачів.
Kyselejsyreček

1
@ Kyselejsyreček цієї відповіді слід уникати будь-якою ціною. У MySQL є достатньо химерностей і запахів, більшість з яких насправді не підтримуються, але зберігаються, щоб уникнути порушення коду, який залежить від цих примх. Модернізація може їх легко зламати або призвести до несподіваних проблем з поведінкою та працездатністю
Panagiotis Kanavos

7

Ви повинні розмістити два повідомлення про оновлення всередині транзакції


2

Ви можете написати оператор оновлення для однієї таблиці, а потім тригер для оновлення першої таблиці , який оновить другу таблицю


0

З моєї точки зору, ви можете зробити це, оновлення двох таблиць у SQL SERVER: від однієї до однієї:

 BEGIN TRANSACTION

      DECLARE @CNSREQ VARCHAR(30)
      DECLARE @ID INT
      DECLARE @CNSRQDT VARCHAR(30)
      DECLARE @ID2 INT

      DECLARE @IDCNSREQ INT
      DECLARE @FINALCNSREQ VARCHAR(30)
      DECLARE @FINALCNSRQDT VARCHAR(30)
      DECLARE @IDCNSRQDT INT


      SET @CNSREQ=(SELECT MIN(REQUISICIONESDT.CNSREQ) FROM REQUISICIONESDT
          INNER JOIN 
              REQUISICIONES
                ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
           AND REQUISICIONES.CNSREQ = REQUISICIONESDT.CNSREQ AND REQUISICIONESDT.IDREQ = REQUISICIONES.ID
        WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID)

      SELECT REQUISICIONES.CNSREQ, REQUISICIONES.ID, REQUISICIONES.CNSRQDT FROM REQUISICIONES
       INNER JOIN 
          REQUISICIONESDT
              ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
               AND REQUISICIONES.CNSREQ = REQUISICIONESDT.CNSREQ AND REQUISICIONESDT.IDREQ = REQUISICIONES.ID
        WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
    AND REQUISICIONES.CNSREQ = @CNSREQ

        UPDATE REQUISICIONESDT SET  REQUISICIONESDT.CNSREQ=NULL, REQUISICIONESDT.IDREQ=NULL
          FROM REQUISICIONES INNER JOIN REQUISICIONESDT
             ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
       WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
      AND REQUISICIONES.CNSREQ = @CNSREQ

        UPDATE REQUISICIONES SET REQUISICIONES.CNSRQDT=NULL, REQUISICIONES.IDRQDT=NULL
          FROM REQUISICIONES INNER JOIN REQUISICIONESDT
          ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
       WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
     AND REQUISICIONES.CNSREQ = @CNSREQ

       SET @ID2=(SELECT MIN(REQUISICIONESDT.ID) FROM REQUISICIONESDT
        WHERE ISNULL(REQUISICIONESDT.IDREQ,0)<>0)
     DELETE FROM REQUISICIONESDT WHERE REQUISICIONESDT.ID=@ID2


      SET @IDCNSREQ=(SELECT MIN (REQUISICIONES.ID)FROM REQUISICIONES
          INNER JOIN REQUISICIONESDT ON
        REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

        SET @FINALCNSREQ=(SELECT MIN (REQUISICIONES.CNSREQ)FROM REQUISICIONES
            INNER JOIN REQUISICIONESDT ON
        REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

         SET @FINALCNSRQDT=(SELECT MIN(REQUISICIONESDT.CNSRQDT) FROM REQUISICIONES
           INNER JOIN REQUISICIONESDT ON
          REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
           WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

          SET @IDCNSRQDT=(SELECT MIN (REQUISICIONESDT.ID)FROM REQUISICIONES
           INNER JOIN REQUISICIONESDT ON
         REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD  
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

           UPDATE REQUISICIONES SET REQUISICIONES.CNSRQDT = @FINALCNSRQDT, REQUISICIONES.IDRQDT=@IDCNSRQDT FROM REQUISICIONES
            INNER JOIN REQUISICIONESDT ON
             REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
            WHERE REQUISICIONESDT.CNSRQDT = @FINALCNSRQDT AND REQUISICIONESDT.ID = @IDCNSRQDT 


ROLLBACK TRANSACTION

-2

Це так само просто, як цей запит, показаний нижче.

UPDATE 
  Table1 T1 join Table2 T2 on T1.id = T2.id
SET 
  T1.LastName='DR. XXXXXX', 
  T2.WAprrs='start,stop'
WHERE 
  T1.id = '010008'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.