Wie aktualisiere ich zwei Tabellen in einer Anweisung in SQL Server 2005?

193

Ich möchte zwei Tabellen auf einmal aktualisieren. Wie mache ich das in 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'
Jango
quelle
4
Es wäre hilfreich, wenn Sie erklären würden, warum.
Eric Mickelsen
2
Ich fürchte, SQL Server 2005 unterstützt nicht das Aktualisieren mehrerer Tabellen in einer Abfrage.
Pranav Singh

Antworten:

194

Sie können nicht mehrere Tabellen in einer Anweisung aktualisieren. Sie können jedoch eine Transaktion verwenden, um sicherzustellen, dass zwei UPDATEAnweisungen atomar behandelt werden. Sie können sie auch stapeln, um eine Rundreise zu vermeiden.

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;
LBushkin
quelle
Eigentlich aktualisiere ich Datensätze dieser beiden Tabellen von einem anderen verlockenden. Versuchbar hat Link zu Tabelle1, aber nicht zu Tabelle2. Wie kann ich denselben Datensatz von Tabelle 2 aktualisieren? Wie werde ich es verlinken?
Jango
@unknown: Basierend auf Ihrem Kommentar müssten Sie beim Aktualisieren von Tabelle2 sowohl Tabelle1 als auch Tabelle2 beitreten, wenn Ihre Aktualisierungsabfrage die Schlüssel aus einer dritten Tabelle benötigt. Unabhängig davon müssen Sie noch zwei separate Updates durchführen.
LBushkin
3
wahrscheinlich nicht verwandt: Dies funktioniert nicht unter MYSQL, da die Update-Syntax für MySQL anders ist. Sie müssten UPDATE Table1, Table2 SET Table1.LastName = 'DR. XXXXXX 'WHERE T1.id = T2.id
Juan Vilar
Müssen
2
Sie sollten Ihre Update-Anweisungen auch in den try / catch-Block einfügen, um eine teilweise Aktualisierung im Fehlerfall zu vermeiden. siehe diese Frage: stackoverflow.com/questions/1749719/…
Mechatroner
84

Sie können nicht zwei Tabellen gleichzeitig aktualisieren, aber Sie können ein Update mit einer Einfügung verknüpfen OUTPUT INTOund diese Ausgabe als Join für das zweite Update verwenden:

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;

Ich habe Ihre Beispielbedingung WHEREin ein anderes Feld als geändert id. Wenn es iddas ist, was Sie nicht brauchen OUTPUT, können Sie nur UPDATEden zweiten Tisch für das gleiche id='010008'.

Remus Rusanu
quelle
Dies ist die beste Antwort und sollte als die wahre Antwort auf die ursprüngliche Frage gewählt werden. Danke dir. Es hat bei mir funktioniert.
Fandango68
1
Soll das T1.fieldsein Table1.field?
WAF
22

Sorry, afaik, das kannst du nicht. Um Attribute in zwei verschiedenen Tabellen zu aktualisieren, müssen Sie zwei separate Anweisungen ausführen. Sie können sich jedoch in einem Stapel befinden (eine Reihe von SQL, die in einem Roundtrip an den Server gesendet werden).

Charles Bretana
quelle
2
Meine Güte! Ich sollte das Wort "Entschuldigung" öfter für zusätzliche Anerkennung verwenden: P
Fandango68
14

Die kurze Antwort darauf lautet nein. Während Sie in der fromKlausel einer Update-Anweisung mehrere Tabellen eingeben können , können Sie nach dem updateSchlüsselwort nur eine einzige Tabelle angeben . Selbst wenn Sie eine "aktualisierbare" Ansicht schreiben (bei der es sich lediglich um eine Ansicht handelt, die bestimmten Einschränkungen folgt), schlagen Aktualisierungen wie diese fehl. Hier sind die relevanten Clips aus der MSDN-Dokumentation (Schwerpunkt liegt bei mir).

UPDATE (Transact-SQL)

Die Ansicht, auf die durch table_or_view_name verwiesen wird, muss aktualisierbar sein und genau eine Basistabelle in der FROM-Klausel der Ansicht referenzieren . Weitere Informationen zu aktualisierbaren Ansichten finden Sie unter CREATE VIEW (Transact-SQL).

CREATE VIEW (Transact-SQL)

Sie können die Daten einer zugrunde liegenden Basistabelle über eine Ansicht ändern, sofern die folgenden Bedingungen erfüllt sind:

  • Alle Änderungen, einschließlich der Anweisungen UPDATE, INSERT und DELETE, müssen auf Spalten aus nur einer Basistabelle verweisen .
  • Die in der Ansicht geänderten Spalten müssen direkt auf die zugrunde liegenden Daten in den Tabellenspalten verweisen. Die Spalten können nicht auf andere Weise abgeleitet werden, z. B. durch Folgendes:
    • Eine Aggregatfunktion: AVG, COUNT, SUMME, MIN, MAX, GROUPING, STDEV, STDEVP, VAR und VARP.
    • Eine Berechnung. Die Spalte kann nicht aus einem Ausdruck berechnet werden, der andere Spalten verwendet. Spalten, die mit den Set-Operatoren UNION, UNION ALL, CROSSJOIN, EXCEPT und INTERSECT erstellt werden, stellen eine Berechnung dar und können ebenfalls nicht aktualisiert werden.
  • Die zu ändernden Spalten sind von den GROUP BY-, HAVING- oder DISTINCT-Klauseln nicht betroffen.
  • TOP wird nirgendwo in der select_statement der Ansicht zusammen mit der WITH CHECK OPTION-Klausel verwendet.

Um ehrlich zu sein, sollten Sie jedoch in Betracht ziehen, zwei verschiedene SQL-Anweisungen innerhalb einer Transaktion gemäß dem Beispiel von LBushkin zu verwenden.

UPDATE: Meine ursprüngliche Behauptung, dass Sie mehrere Tabellen in einer aktualisierbaren Ansicht aktualisieren könnten, war falsch. Unter SQL Server 2005 und 2012 wird der folgende Fehler generiert. Ich habe meine Antwort korrigiert, um dies widerzuspiegeln.

Msg 4405, Level 16, State 1, Line 1

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

jveazey
quelle
1
Während es nicht möglich ist, ein View-Objekt zu aktualisieren, das mehrere Tabellen betrifft , können Sie STATT Trigger erstellen, die das Original in separate Anweisungen 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.
aufteilen
9

Dies funktioniert für MySQL und ist eigentlich nur eine implizite Transaktion, aber es sollte ungefähr so ​​aussehen:

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'

Wenn Sie Aktualisierungen an mehreren Tabellen durchführen, für die mehrere Anweisungen erforderlich sind. Dies ist wahrscheinlich möglich, wenn Sie eine und eine andere basierend auf anderen Bedingungen aktualisieren. Sie sollten eine Transaktion verwenden. 

user3662407
quelle
1
Dieser Anser ist für andere Benutzer weiterhin relevant.
Kyselejsyreček
1
@ Kyselejsyreček diese Antwort sollte unter allen Umständen vermieden werden. MySQL hat genug Macken und Gerüche, von denen die meisten nicht unterstützt werden, aber beibehalten werden, um zu vermeiden, dass Code beschädigt wird, der von diesen Macken abhängt. Ein Upgrade kann sie leicht
beschädigen
7

Sie sollten zwei Update-Anweisungen in eine Transaktion einfügen

Mick
quelle
2

Sie können eine Aktualisierungsanweisung für eine Tabelle und dann einen Auslöser für die Aktualisierung der ersten Tabelle schreiben , wodurch die zweite Tabelle aktualisiert wird

Sandip - Full Stack Entwickler
quelle
0

Aus meiner Sicht können Sie dies tun, indem Sie zwei Tabellen in SQL SERVER eins zu eins aktualisieren:

 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
Ricardo Roa
quelle
-2

Es ist so einfach wie diese unten gezeigte Abfrage.

UPDATE 
  Table1 T1 join Table2 T2 on T1.id = T2.id
SET 
  T1.LastName='DR. XXXXXX', 
  T2.WAprrs='start,stop'
WHERE 
  T1.id = '010008'
Mohit Gupta
quelle