UPDATE (Transact-SQL)

Ändert vorhandene Daten in einer oder mehreren Spalten in einer Tabelle oder Sicht in SQL Server 2008 R2. Beispiele finden Sie unter Beispiele.

Themenlink (Symbol)Transact-SQL-Syntaxkonventionen

Syntax

[ WITH <common_table_expression> [...n] ]
UPDATE 
    [ TOP ( expression ) [ PERCENT ] ] 
    { { table_alias | <object> | rowset_function_limited 
         [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
      }
      | @table_variable    
    }
    SET
        { column_name = { expression | DEFAULT | NULL }
          | { udt_column_name.{ { property_name = expression
                                | field_name = expression }
                                | method_name ( argument [ ,...n ] )
                              }
            }
          | column_name { .WRITE ( expression , @Offset , @Length ) }
          | @variable = expression
          | @variable = column = expression
          | column_name { += | -= | *= | /= | %= | &= | ^= | |= } expression
          | @variable { += | -= | *= | /= | %= | &= | ^= | |= } expression
          | @variable = column { += | -= | *= | /= | %= | &= | ^= | |= } expression
        } [ ,...n ] 

    [ <OUTPUT Clause> ]
    [ FROM { <table_source> } [ ,...n ] ] 
    [ WHERE { <search_condition> 
            | { [ CURRENT OF 
                  { { [ GLOBAL ] cursor_name } 
                      | cursor_variable_name 
                  } 
                ]
              }
            } 
    ] 
    [ OPTION ( <query_hint> [ ,...n ] ) ]
[ ; ]

<object> ::=
{ 
    [ server_name . database_name . schema_name . 
    | database_name .[ schema_name ] . 
    | schema_name .
    ]
    table_or_view_name}

Argumente

  • WITH <common_table_expression>
    Gibt den temporären Resultset- oder Sichtnamen an, der auch als allgemeiner Tabellenausdruck (CTE, Common Table Expression) bezeichnet wird und innerhalb der UPDATE-Anweisung definiert ist. Das Resultset des allgemeinen Tabellenausdrucks wird von einer einfachen Abfrage abgeleitet. Die UPDATE-Anweisung verweist auf dieses Resultset. Weitere Informationen finden Sie unter WITH common_table_expression (Transact-SQL).

  • TOP ( expression**)** [ PERCENT ]
    Gibt die Anzahl oder den Prozentsatz der Zeilen an, die aktualisiert werden. expression kann entweder eine Anzahl oder ein Prozentsatz von Zeilen sein.

    Die Zeilen, auf die im mit INSERT, UPDATE, MERGE oder DELETE verwendeten TOP-Ausdruck verwiesen wird, sind nicht in einer bestimmten Reihenfolge angeordnet.

    In den Anweisungen INSERT, UPDATE, MERGE und DELETE sind Klammern erforderlich, die expression in TOP begrenzen. Weitere Informationen finden Sie unter TOP (Transact-SQL).

  • table_alias
    Der in der FROM-Klausel angegebene Alias, der die Tabelle oder Sicht darstellt, aus der die Zeilen aktualisiert werden sollen.

  • server_name
    Der Name des Verbindungsservers, auf dem sich die Tabelle oder Sicht befindet. server_name kann als Name eines Verbindungsservers oder mithilfe der OPENDATASOURCE-Funktion angegeben werden.

    Wenn server_name als Verbindungsserver angegeben wird, sind database_name und schema_name erforderlich. Wenn server_name mit OPENDATASOURCE angegeben wird, gelten database_name und schema_name möglicherweise nicht für alle Datenquellen und unterliegen den Funktionen des OLE DB-Anbieters, der auf das Remoteobjekt zugreift. Weitere Informationen finden Sie unter Verteilte Abfragen.

  • database_name
    Der Name der Datenbank.

  • schema_name
    Der Name des Schemas, zu dem die Tabelle oder Sicht gehört.

  • table_or view_name
    Der Name der Tabelle oder Sicht, aus der die Zeilen aktualisiert werden sollen. Die Sicht, auf die table_or_view_name verweist, muss aktualisierbar sein und auf genau eine Basistabelle in der FROM-Klausel der Sicht verweisen. Weitere Informationen zu aktualisierbaren Sichten finden Sie unter CREATE VIEW (Transact-SQL).

  • rowset_function_limited
    Die OPENQUERY-Funktion oder die OPENROWSET-Funktion. Die Verwendung dieser Funktionen unterliegt den Funktionen des OLE DB-Anbieters, der auf das Remoteobjekt zugreift. Weitere Informationen finden Sie unter Verteilte Abfragen.

  • WITH ( <Table_Hint_Limited> )
    Gibt mindestens einen Tabellenhinweis an, der für eine Zieltabelle zulässig ist. Das WITH-Schlüsselwort und die Klammern sind erforderlich. NOLOCK und READUNCOMMITTED sind nicht zulässig. Weitere Informationen zu Tabellenhinweisen finden Sie unter Tabellenhinweise (Transact-SQL).

  • @table_variable
    Gibt eine table-Variable als Tabellenquelle an.

  • SET
    Gibt die Liste der zu aktualisierenden Spalten- oder Variablennamen an.

  • column_name
    Eine Spalte, die die zu ändernden Daten enthält. column_name muss in table_or view_name vorhanden sein. Identitätsspalten können nicht aktualisiert werden.

  • expression
    Eine Variable, ein Literalwert, ein Ausdruck oder eine SELECT-Anweisung als Unterabfrage in Klammern, die bzw. der einen einzelnen Wert zurückgibt. Der von expression zurückgegebene Wert ersetzt den vorhandenen Wert in column_name oder @variable.

    HinweisHinweis

    In Verweisen auf die Unicode-Zeichendatentypen nchar, nvarchar und ntext muss "expression" der Großbuchstabe "N" vorangestellt werden. Wenn "N" nicht angegeben wird, konvertiert SQL Server die Zeichenfolge in die Codepage, die der Standardsortierung der Datenbank oder Spalte entspricht. Alle Zeichen, die in der betreffenden Codepage nicht gefunden werden, gehen verloren.

  • DEFAULT
    Gibt an, dass der vorhandene Wert in der Spalte durch den für die Spalte definierten Standardwert ersetzt werden soll. Damit kann auch die Spalte auf NULL geändert werden, wenn diese keinen Standard aufweist und NULL-Werte zulässt.

  • { += | -= | *= | /= | %= | &= | ^= | |= }
    Verbundzuweisungsoperator:

    += Addition und Zuweisung

    -= Subtraktion und Zuweisung

    *= Multiplikation und Zuweisung

    /= Division und Zuweisung

    %= Modulo und Zuweisung

    &= Bitweises AND und Zuweisung

    ^= Bitweises XOR und Zuweisung

    |= Bitweises OR und Zuweisung

    Weitere Informationen finden Sie unter Verbundoperatoren (Transact-SQL).

  • udt_column_name
    Eine benutzerdefinierte Spalte.

  • property_name | field_name
    Eine öffentliche Eigenschaft oder ein öffentliches Datenelement eines benutzerdefinierten Typs.

  • method_name(argument [ ,... n] )
    Eine nicht statische, öffentliche Mutatormethode von udt_column_name, die ein oder mehrere Argumente umfassen kann.

  • **.**WRITE (expression,@Offset,@Length)
    Gibt an, dass ein Abschnitt des Werts von column_name geändert werden soll. expression ersetzt @Length-Einheiten, beginnend mit @Offset von column_name. Nur Spalten des Typs varchar(max), nvarchar(max) oder varbinary(max) können mit dieser Klausel angegeben werden. column_name darf nicht NULL sein und kann nicht mit einem Tabellennamen oder Tabellenalias qualifiziert werden.

    expression ist der Wert, der in column_name kopiert wird. expression muss in den column_name-Typ ausgewertet werden oder implizit umgewandelt werden können. Wenn expression auf NULL festgelegt wird, wird @Length ignoriert, und der Wert in column_name wird am angegebenen @Offset abgeschnitten.

    @Offset ist der Startpunkt im Wert von column_name, an dem expression geschrieben wird. @Offset ist eine auf Null basierende Ordnungsposition, vom Typ bigint und darf keine negative Zahl sein. Wenn @Offset NULL ist, hängt der Aktualisierungsvorgang expression am Ende des vorhandenen column_name-Werts an, und @Length wird ignoriert. Falls @Offset größer als die Länge von column_name ist, gibt Database Engine (Datenbankmodul) einen Fehler zurück. Wenn @Offset zuzüglich @Length das Ende des zugrunde liegenden Werts in der Spalte übersteigt, findet der Löschvorgang bis zum letzten Zeichen des Werts statt. Wenn @Offset zuzüglich LEN(expression) größer als die zugrunde liegende deklarierte Größe ist, wird ein Fehler ausgelöst.

    @Length ist die Länge des Abschnitts in der Spalte, beginnend mit @Offset, der durch expression ersetzt wird. @Length ist vom Typ bigint und darf keine negative Zahl sein. Wenn @Length NULL ist, entfernt der Aktualisierungsvorgang alle Daten aus @Offset bis zum Ende des column_name-Werts.

    Weitere Informationen finden Sie in den Hinweisen.

  • @variable
    Eine deklarierte Variable, die auf den von expression zurückgegebenen Wert festgelegt wird.

    SET @variable = column = expression legt die Variable auf denselben Wert wie die Spalte fest. Diese Anweisung unterscheidet sich von SET @variable = column, column = expression, wodurch die Variable auf den Wert der Spalte vor der Aktualisierung festgelegt wird.

  • <OUTPUT_Clause>
    Gibt aktualisierte Daten oder Ausdrücke zurück, die darauf als Teil des UPDATE-Vorgangs basieren. Die OUTPUT-Klausel wird nicht in DML-Anweisungen unterstützt, die an Remotetabellen oder -sichten gerichtet sind. Weitere Informationen finden Sie unter OUTPUT-Klausel (Transact-SQL).

  • FROM <table_source>
    Gibt an, dass eine Tabelle, Sicht oder abgeleitete Tabelle als Quelle die Kriterien für den Aktualisierungsvorgang bereitstellen soll. Weitere Informationen finden Sie unter FROM (Transact-SQL).

    Wenn das Objekt, das aktualisiert wird, mit dem Objekt in der FROM-Klausel identisch ist und nur ein Verweis auf das Objekt in der FROM-Klausel vorhanden ist, kann ein Objektalias angegeben werden. Wenn das Objekt, das aktualisiert wird, mehrmals in der FROM-Klausel vorhanden ist, darf genau ein Verweis auf das Objekt keinen Tabellenalias angeben. Alle anderen Verweise auf das Objekt in der FROM-Klausel müssen einen Objektalias aufweisen.

    Eine Sicht mit einem INSTEAD OF UPDATE-Trigger kann nicht Ziel für eine UPDATE-Anweisung mit einer FROM-Klausel sein.

    HinweisHinweis

    Jeder Aufruf von OPENDATASOURCE, OPENQUERY oder OPENROWSET in der FROM-Klausel wird separat und unabhängig von Aufrufen dieser Funktionen ausgewertet, die als Ziel der Aktualisierung verwendet werden. Dies ist auch dann der Fall, wenn identische Argumente für die beiden Aufrufe angegeben werden. Insbesondere haben Filter- oder Verknüpfungsbedingungen, die auf das Ergebnis eines dieser Aufrufe angewendet werden, keinen Einfluss auf die Ergebnisse des anderen Aufrufs.

  • WHERE
    Gibt die Bedingungen an, mit denen die zu aktualisierenden Zeilen eingegrenzt werden. Es gibt zwei Arten von Aktualisierungen, die vom verwendeten WHERE-Klauseltyp abhängen:

    • Gesuchte Aktualisierungen legen eine Suchbedingung fest, der die zu löschenden Zeilen entsprechen müssen.

    • Positionierte Aktualisierungen verwenden die CURRENT OF-Klausel, um einen Cursor anzugeben. Der Aktualisierungsvorgang wird an der aktuellen Position des Cursors ausgeführt.

  • <search_condition>
    Bezeichnet die Bedingung, die erfüllt sein muss, damit die Zeilen aktualisiert werden. Die Suchbedingung kann auch die Bedingung sein, auf der ein Join basiert. Es gibt keinen Höchstwert hinsichtlich der Anzahl von Prädikaten in einer Suchbedingung. Weitere Informationen zu Prädikaten und Suchbedingungen finden Sie unter Suchbedingung (Transact-SQL).

  • CURRENT OF
    Gibt an, dass die Aktualisierung an der aktuellen Position des angegebenen Cursors ausgeführt wird.

  • GLOBAL
    Gibt an, dass cursor_name auf einen globalen Cursor verweist.

  • cursor_name
    Der Name des geöffneten Cursors, von dem der Abruf erfolgen soll. Wenn sowohl ein globaler als auch ein lokaler Cursor namens cursor_name vorhanden sind, bezieht sich dieses Argument auf den globalen Cursor, wenn GLOBAL angegeben ist. Andernfalls bezieht es sich auf den lokalen Cursor. Der Cursor muss Aktualisierungen zulassen.

  • cursor_variable_name
    Der Name der Cursorvariablen. cursor_variable_name muss auf einen Cursor verweisen, der Aktualisierungen zulässt.

  • OPTION ( <query_hint> [ ,... n ] )
    Gibt an, dass mithilfe von Optimierungshinweisen angepasst wird, wie die Anweisung von Database Engine (Datenbankmodul) verarbeitet wird. Weitere Informationen finden Sie unter Abfragehinweise (Transact-SQL).

Bewährte Methoden

Variablennamen können in UPDATE-Anweisungen verwendet werden, um die betroffenen alten und neuen Werte anzuzeigen. Diese Vorgehensweise sollte aber nur angewendet werden, wenn die UPDATE-Anweisung einen einzelnen Datensatz betrifft. Betrifft die UPDATE-Anweisung mehrere Datensätze, verwenden Sie die OUTPUT-Klausel, um die alten und neuen Werte für die einzelnen Datensätze zurückzugeben.

Gehen Sie beim Angeben der FROM-Klausel zum Bereitstellen der Kriterien für den Aktualisierungsvorgang vorsichtig vor. Die Ergebnisse einer UPDATE-Anweisung sind nicht definiert, wenn sie nicht deterministisch ist. Dies ist der Fall, wenn die UPDATE-Anweisung eine FROM-Klausel enthält, in der nicht für jedes Vorkommen einer zu aktualisierenden Spalte genau ein Wert verfügbar ist. Dies kann zu unerwarteten Ergebnissen führen. Beispielsweise erfüllen im folgenden Skript der UPDATE-Anweisung beide Zeilen in Table1 die Bedingungen der FROM-Klausel in der UPDATE-Anweisung. Es ist jedoch nicht definiert, welche Zeile aus Table1 zum Aktualisieren der Zeile in Table2 verwendet wird.

USE AdventureWorks2008R2;
GO
IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL
    DROP TABLE dbo.Table1;
GO
IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL
    DROP TABLE dbo.Table2;
GO
CREATE TABLE dbo.Table1 
    (ColA int NOT NULL, ColB decimal(10,3) NOT NULL);
GO
CREATE TABLE dbo.Table2 
    (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);
GO
INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0);
INSERT INTO dbo.Table2 VALUES(1, 0.0);
GO
UPDATE dbo.Table2 
SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB
FROM dbo.Table2 
    INNER JOIN dbo.Table1 
    ON (dbo.Table2.ColA = dbo.Table1.ColA);
GO
SELECT ColA, ColB 
FROM dbo.Table2;

Das gleiche Problem kann auftreten, wenn die FROM-Klausel und die WHERE CURRENT OF-Klausel kombiniert werden. Im folgenden Beispiel erfüllen beide Zeilen in Table2 die Bedingungen der FROM-Klausel in der UPDATE-Anweisung. Es ist jedoch nicht definiert, welche Zeile aus Table2 zum Aktualisieren der Zeile in Table1 verwendet wird.

USE AdventureWorks2008R2;
GO
IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL
    DROP TABLE dbo.Table1;
GO
IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL
    DROP TABLE dbo.Table2;
GO
CREATE TABLE dbo.Table1
    (c1 int PRIMARY KEY NOT NULL, c2 int NOT NULL);
GO
CREATE TABLE dbo.Table2
    (d1 int PRIMARY KEY NOT NULL, d2 int NOT NULL);
GO
INSERT INTO dbo.Table1 VALUES (1, 10);
INSERT INTO dbo.Table2 VALUES (1, 20), (2, 30);
GO
DECLARE abc CURSOR LOCAL FOR
    SELECT c1, c2 
    FROM dbo.Table1;
OPEN abc;
FETCH abc;
UPDATE dbo.Table1 
SET c2 = c2 + d2 
FROM dbo.Table2 
WHERE CURRENT OF abc;
GO
SELECT c1, c2 FROM dbo.Table1;
GO

Kompatibilitätsunterstützung

SET ROWCOUNT wird in einer künftigen Version von SQL Server keine Auswirkungen auf die Anweisungen DELETE, INSERT und UPDATE haben. Verwenden Sie SET ROWCOUNT bei neuen Entwicklungsarbeiten nicht zusammen mit den Anweisungen DELETE, INSERT und UPDATE, und planen Sie die Änderung von Anwendungen, die SET ROWCOUNT derzeit verwenden. Es wird empfohlen, die TOP-Syntax zu verwenden.

Die Unterstützung für die Verwendung der READUNCOMMITTED- und NOLOCK-Hinweise in der FROM-Klausel, die sich auf die Zieltabelle einer UPDATE- oder DELETE-Anweisung beziehen, wird in einer zukünftigen Version von SQL Server entfernt. Vermeiden Sie die Verwendung dieser Hinweise in diesem Kontext beim Entwickeln neuer Anwendungen, und planen Sie die Änderung von Anwendungen, in denen sie aktuell verwendet werden.

Datentypen

Alle char-Spalten und nchar-Spalten werden rechts auf die definierte Länge aufgefüllt.

Wenn ANSI_PADDING auf OFF festgelegt ist, werden alle nachfolgenden Leerzeichen aus den in varchar-Spalten und nvarchar-Spalten eingefügten Daten entfernt. Dies gilt nicht für Zeichenfolgen, die nur aus Leerzeichen bestehen. Diese Zeichenfolgen werden auf eine leere Zeichenfolge abgeschnitten. Wenn ANSI_PADDING auf ON festgelegt ist, werden nachfolgende Leerzeichen eingefügt. Der Microsoft SQL Server-ODBC-Treiber und der OLE DB-Provider für SQL Server stellen beim Herstellen einer Verbindung SET ANSI_PADDING automatisch auf ON ein. Diese Einstellung kann in ODBC-Datenquellen oder durch Festlegen von Verbindungsattributen oder Verbindungseigenschaften konfiguriert werden. Weitere Informationen finden Sie unter SET ANSI_PADDING (Transact-SQL).

Aktualisieren von Datentypen mit umfangreichen Werten

Verwenden Sie die .WRITE (expression, @Offset, @Length)-Klausel zum Ausführen einer teilweisen oder vollständigen Aktualisierung der Datentypen varchar(max), nvarchar(max) und varbinary(max). Bei einer teilweisen Aktualisierung einer varchar(max)-Spalte werden z. B. nur die ersten 200 Zeichen der Spalte gelöscht oder geändert, während bei einer vollständigen Aktualisierung alle Daten in der Spalte gelöscht oder geändert werden.

Es wird empfohlen, Daten in Blockgrößen einzufügen bzw. zu aktualisieren, die ein Vielfaches von 8.040 Byte sind, um eine optimale Leistung zu erzielen.

Database Engine (Datenbankmodul) konvertiert eine teilweise Aktualisierung in eine vollständige Aktualisierung, wenn die UPDATE-Anweisung eine dieser Aktionen bewirkt:

  • Ändert eine Schlüsselspalte der partitionierten Sicht oder Tabelle.

  • Ändert mehr als eine Zeile und aktualisiert außerdem den Schlüssel eines nicht eindeutigen gruppierten Index in einen nicht konstanten Wert.

Sie können die .WRITE-Klausel nicht zum Aktualisieren einer NULL-Spalte oder zum Festlegen des Werts von column_name auf NULL verwenden.

@Offset und @Length werden in Byte für varbinary- und varchar-Datentypen und in Zeichen für den nvarchar-Datentyp angegeben. Die geeigneten Offsets werden für Doppelbyte-Zeichensatzsortierungen (DBCS, Double-Byte Character Set) berechnet.

Wenn in einer OUTPUT-Klausel auf die von der .WRITE-Klausel geänderte Spalte verwiesen wird, wird der vollständige Wert der Spalte (entweder das Anfangsimage in deleted.column_name oder das Endimage in inserted.column_name) an die angegebene Spalte in der Tabellenvariablen zurückgegeben.

Verwenden Sie STUFF (Transact-SQL), um dieselbe Funktionalität von .WRITE mit anderen Zeichen- oder Binärdatentypen zu erzielen.

Aktualisieren von FILESTREAM-Daten

Sie können ein FILESTREAM-Feld mithilfe der UPDATE-Anweisung auf einen NULL-Wert, einen leeren Wert oder eine relativ kleine Menge von Inlinedaten aktualisieren. Große Datenmengen lassen sich jedoch mithilfe von Win32-Schnittstellen effizienter in eine Datei streamen. Wenn Sie ein FILESTREAM-Feld aktualisieren, ändern Sie die zugrunde liegenden BLOB-Daten im Dateisystem. Wenn ein FILESTREAM-Feld auf NULL festgelegt wird, werden die dem Feld zugeordneten BLOB-Daten gelöscht. Dabei kann .WRITE() nicht zur teilweisen Aktualisierung der Daten eingesetzt werden. Weitere Informationen finden Sie unter Übersicht über FILESTREAM.

Aktualisieren der Spalten "text", "ntext" und "image"

Durch das Ändern einer Spalte des Datentyps text, ntext oder image mit UPDATE wird die Spalte initialisiert, ein gültiger Textzeiger zugewiesen und mindestens eine Datenseite zugeordnet, es sei denn, die Spalte wird mit NULL aktualisiert. Wenn die UPDATE-Anweisung beim Aktualisieren des Clusteringschlüssels und mindestens einer Spalte text, ntext oder image nicht mehr als eine Zeile ändern konnte, wird die Teilaktualisierung dieser Spalten als vollständige Ersetzung dieser Werte ausgeführt.

Wenn Sie große Datenblöcke des Datentyps text, ntext oder image ersetzen oder ändern, verwenden Sie statt der UPDATE-Anweisung die WRITETEXT-Anweisung oder die UPDATETEXT-Anweisung.

Wichtiger HinweisWichtig

Die Datentypen ntext, text und image werden in einer zukünftigen Version von Microsoft SQL Server entfernt. Vermeiden Sie die Verwendung dieser Datentypen bei neuen Entwicklungen, und planen Sie die Änderung von Anwendungen, in denen sie aktuell verwendet werden. Verwenden Sie stattdessen nvarchar(max), varchar(max) und varbinary(max). Weitere Informationen finden Sie unter Verwenden von Datentypen mit umfangreichen Werten.

Fehlerbehandlung

Sie können die Fehlerbehandlung für die UPDATE-Anweisung durch Angeben der Anweisung in einem TRY…CATCH-Konstrukt implementieren. Weitere Informationen finden Sie unter Verwenden von TRY...CATCH in Transact-SQL.

Wenn die Aktualisierung einer Zeile eine Einschränkung oder Regel oder die NULL-Einstellung für die Spalte verletzt oder der Datentyp des neuen Werts inkompatibel ist, wird die Anweisung abgebrochen. Außerdem wird ein Fehler zurückgegeben, und es werden keine Datensätze aktualisiert.

Wenn in einer UPDATE-Anweisung ein arithmetischer Fehler (Überlauf, Division durch Null oder Definitionsbereichsfehler/Domänenfehler) bei der Auswertung eines Ausdrucks auftritt, wird die Aktualisierung nicht ausgeführt. Der Rest des Batches wird nicht ausgeführt, und eine Fehlermeldung wird zurückgegeben.

Wenn die Aktualisierung mindestens einer Spalte eines gruppierten Index dazu führt, dass die Größe des gruppierten Index und der Zeile den Wert von 8.060 Byte überschreitet, tritt bei der Aktualisierung ein Fehler auf, und es wird eine Fehlermeldung zurückgegeben.

Interoperabilität

UPDATE-Anweisungen sind im Textkörper von benutzerdefinierten Funktionen nur zulässig, wenn es sich bei der Tabelle, die geändert wird, um eine Tabellenvariable handelt.

Wenn ein INSTEAD OF-Trigger für UPDATE-Aktionen für eine Tabelle definiert ist, wird der Trigger statt der UPDATE-Anweisung ausgeführt. Frühere Versionen von SQL Server unterstützen nur AFTER-Trigger für UPDATE-Anweisungen und andere Anweisungen zur Datenänderung.

Einschränkungen

Die FROM-Klausel kann nicht in einer UPDATE-Anweisung angegeben werden, die (direkt oder indirekt) auf eine Sicht verweist, für die ein INSTEAD OF-Trigger definiert wurde. Weitere Informationen zu INSTEAD OF-Triggern finden Sie unter CREATE TRIGGER (Transact-SQL).

Die Einstellung der SET ROWCOUNT-Option wird für UPDATE-Anweisungen ignoriert, die für Remotetabellen und partitionierte Sichten (lokal und remote) ausgeführt werden.

Wenn ein allgemeiner Tabellenausdruck das Ziel einer UPDATE-Anweisung ist, müssen alle Verweise auf den allgemeinen Tabellenausdruck in der Anweisung übereinstimmen. Wenn dem allgemeinen Tabellenausdruck z. B. ein Alias in der FROM-Klausel zugewiesen wird, muss der Alias für alle weiteren Verweise auf den allgemeinen Tabellenausdruck verwendet werden. Eindeutige Verweise auf allgemeine Tabellenausdrücke sind erforderlich, da ein allgemeiner Tabellenausdruck keine Objekt-ID hat, mit der SQL Server die implizite Beziehung zwischen einem Objekt und seinem Alias erkennt. Ohne diese Beziehung erzeugt der Abfrageplan möglicherweise ein unerwartetes Joinverhalten und unbeabsichtigte Abfrageergebnisse. In den folgenden Beispielen werden richtige und falsche Methoden zum Angeben eines allgemeinen Tabellenausdrucks veranschaulicht, wenn der allgemeine Tabellenausdruck das Zielobjekt des Aktualisierungsvorgangs ist.

USE tempdb;
GO
-- UPDATE statement with CTE references that are correctly matched.
DECLARE @x TABLE (ID int, Value int);
DECLARE @y TABLE (ID int, Value int);
INSERT @x VALUES (1, 10), (2, 20);
INSERT @y VALUES (1, 100),(2, 200);

WITH cte AS (SELECT * FROM @x)
UPDATE x -- cte is referenced by the alias.
SET Value = y.Value
FROM cte AS x  -- cte is assigned an alias.
INNER JOIN @y AS y ON y.ID = x.ID;
SELECT * FROM @x;
GO

Dies ist das Resultset.

ID     Value

------ -----

1      100

2      200

(2 row(s) affected)

-- UPDATE statement with CTE references that are incorrectly matched.
USE tempdb;
GO
DECLARE @x TABLE (ID int, Value int);
DECLARE @y TABLE (ID int, Value int);
INSERT @x VALUES (1, 10), (2, 20);
INSERT @y VALUES (1, 100),(2, 200);

WITH cte AS (SELECT * FROM @x)
UPDATE cte   -- cte is not referenced by the alias.
SET Value = y.Value
FROM cte AS x  -- cte is assigned an alias.
INNER JOIN @y AS y ON y.ID = x.ID; 
SELECT * FROM @x; 
GO

Dies ist das Resultset.

ID     Value

------ -----

1      100

2      100

(2 row(s) affected)

Protokollierungsverhalten

Die UPDATE-Anweisung wird vollständig protokolliert. Aktualisierungen mit .WRITE, bei denen neue Daten eingefügt oder angefügt werden, werden minimal protokolliert, wenn das Wiederherstellungsmodell für die Datenbank auf massenprotokolliert oder einfach festgelegt ist. Die minimale Protokollierung wird nicht verwendet, wenn mit .WRITE vorhandene Werte aktualisiert werden. Weitere Informationen finden Sie unter Vorgänge, für die eine minimale Protokollierung verfügbar ist.

Sicherheit

Berechtigungen

Für die Zieltabelle sind UPDATE-Berechtigungen erforderlich. SELECT-Berechtigungen sind zum Aktualisieren der Tabelle ebenfalls erforderlich, wenn die UPDATE-Anweisung eine WHERE-Klausel enthält oder wenn expression in der SET-Klausel eine Spalte in der Tabelle verwendet.

UPDATE-Berechtigungen werden standardmäßig Mitgliedern der festen Serverrolle sysadmin und der festen Datenbankrollen db_owner und db_datawriter sowie Tabellenbesitzern erteilt. Mitglieder der Rollen sysadmin, db_owner und db_securityadmin sowie der Tabellenbesitzer können Berechtigungen an andere Benutzer übertragen.

Beispiele

Kategorie

Funktionssyntaxelemente

Grundlegende Syntax

UPDATE

Eingrenzen der zu aktualisierenden Zeilen

WHERE • TOP • WITH allgemeiner Tabellenausdruck • WHERE CURRENT OF

Festlegen von Spaltenwerten

berechnete Werte • Verbundoperatoren • Standardwerte • Unterabfragen

Angeben von Zielobjekten, die keine Standardtabellen sind

Sichten • Tabellenvariablen • Tabellenaliase

Aktualisieren von Daten auf Grundlage von Daten aus anderen Tabellen

FROM

Aktualisieren von Zeilen in einer Remotetabelle

Verbindungsserver • OPENQUERY • OPENDATASOURCE

Aktualisieren von Large Object-Datentypen

.WRITE • OPENROWSET

Aktualisieren benutzerdefinierter Typen

Benutzerdefinierte Typen

Außerkraftsetzen des Standardverhaltens des Abfrageoptimierers mithilfe von Hinweisen

Tabellenhinweise • Abfragehinweise

Erfassen der Ergebnisse der UPDATE-Anweisung

OUTPUT-Klausel

Verwenden von UPDATE in anderen Anweisungen

Gespeicherte Prozeduren • TRY…CATCH

Grundlegende Syntax

Die Beispiele in diesem Abschnitt veranschaulichen die grundlegende Funktion der UPDATE-Anweisung mit der mindestens erforderlichen Syntax.

A. Verwenden einer einfachen UPDATE-Anweisung

Im folgenden Beispiel wird eine einzelne Spalte für alle Zeilen in der Person.Address-Tabelle aktualisiert.

USE AdventureWorks2008R2;
GO
UPDATE Person.Address
SET ModifiedDate = GETDATE();

B. Aktualisieren mehrerer Spalten

Im folgenden Beispiel werden die Werte in den Spalten Bonus, CommissionPct und SalesQuota für alle Zeilen in der SalesPerson-Tabelle aktualisiert.

USE AdventureWorks2008R2;
GO
UPDATE Sales.SalesPerson
SET Bonus = 6000, CommissionPct = .10, SalesQuota = NULL;
GO

Eingrenzen der zu aktualisierenden Zeilen

Die Beispiele in diesem Abschnitt veranschaulichen Methoden, mit denen die Anzahl der von der UPDATE-Anweisung betroffenen Zeilen eingegrenzt werden kann.

A. Verwenden der WHERE-Klausel

Im folgenden Beispiel wird die WHERE-Klausel verwendet, um die zu aktualisierenden Zeilen anzugeben. Die Anweisung aktualisiert den Wert in der Spalte Color der Tabelle Production.Product für alle Zeilen, die in der Spalte Color den vorhandenen Wert "Red" aufweisen und einen Wert in der Spalte Name aufweisen, der mit "Road-250" beginnt.

USE AdventureWorks2008R2;
GO
UPDATE Production.Product
SET Color = N'Metallic Red'
WHERE Name LIKE N'Road-250%' AND Color = N'Red';
GO

B. Verwenden der TOP-Klausel

In den folgenden Beispielen wird mithilfe der TOP-Klausel die Anzahl der Zeilen beschränkt, die in einer UPDATE-Anweisung geändert werden. Wenn eine TOP (n)-Klausel zusammen mit UPDATE verwendet wird, wird der Aktualisierungsvorgang für eine zufällige Auswahl von n Zeilen ausgeführt. Im folgenden Beispiel wird die VacationHours-Spalte um 25 Prozent für 10 zufällige Zeilen in der Employee-Tabelle aktualisiert.

USE AdventureWorks2008R2;
GO
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25 ;
GO

Wenn TOP verwendet werden muss, um Aktualisierungen in einer sinnvollen Abfolge anzuwenden, muss in einer untergeordneten SELECT-Anweisung TOP gemeinsam mit ORDER BY verwendet werden. Im folgenden Beispiel werden die Urlaubsstunden der 10 Mitarbeiter mit dem frühesten Einstellungsdatum aktualisiert.

UPDATE HumanResources.Employee
SET VacationHours = VacationHours + 8
FROM (SELECT TOP 10 BusinessEntityID FROM HumanResources.Employee
     ORDER BY HireDate ASC) AS th
WHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID;
GO

C. Verwenden der WITH common_table_expression-Klausel

Im folgenden Beispiel wird der PerAssemnblyQty-Wert für alle Teile und Komponenten aktualisiert, die direkt oder indirekt zum Erstellen der ProductAssemblyID 800 verwendet werden. Der allgemeine Tabellenausdruck gibt eine hierarchische Liste mit Teilen zurück, die zum Erstellen der ProductAssemblyID 800 direkt verwendet werden, sowie mit Teilen, die zum Erstellen dieser Komponenten verwendet werden, usw. Nur die Zeilen, die vom allgemeinen Tabellenausdruck zurückgegeben werden, werden verändert. Weitere Informationen zu rekursiven allgemeinen Tabellenausdrücken finden Sie unter Rekursive Abfragen mithilfe von allgemeinen Tabellenausdrücken.

USE AdventureWorks2008R2;
GO
WITH Parts(AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS
(
    SELECT b.ProductAssemblyID, b.ComponentID, b.PerAssemblyQty,
        b.EndDate, 0 AS ComponentLevel
    FROM Production.BillOfMaterials AS b
    WHERE b.ProductAssemblyID = 800
          AND b.EndDate IS NULL
    UNION ALL
    SELECT bom.ProductAssemblyID, bom.ComponentID, p.PerAssemblyQty,
        bom.EndDate, ComponentLevel + 1
    FROM Production.BillOfMaterials AS bom 
        INNER JOIN Parts AS p
        ON bom.ProductAssemblyID = p.ComponentID
        AND bom.EndDate IS NULL
)
UPDATE Production.BillOfMaterials
SET PerAssemblyQty = c.PerAssemblyQty * 2
FROM Production.BillOfMaterials AS c
JOIN Parts AS d ON c.ProductAssemblyID = d.AssemblyID
WHERE d.ComponentLevel = 0; 

D. Verwenden der WHERE CURRENT OF-Klausel

Im folgenden Beispiel wird die WHERE CURRENT OF-Klausel verwendet, um nur die Zeile zu aktualisieren, auf die der Cursor positioniert ist. Wenn ein Cursor auf einem Join basiert, wird nur die Tabelle geändert, die mit table_name in der UPDATE-Anweisung angegeben wurde. Andere im Cursor enthaltene Tabellen sind davon nicht betroffen.

USE AdventureWorks2008R2;
GO
DECLARE complex_cursor CURSOR FOR
    SELECT a.BusinessEntityID
    FROM HumanResources.EmployeePayHistory AS a
    WHERE RateChangeDate <> 
         (SELECT MAX(RateChangeDate)
          FROM HumanResources.EmployeePayHistory AS b
          WHERE a.BusinessEntityID = b.BusinessEntityID) ;
OPEN complex_cursor;
FETCH FROM complex_cursor;
UPDATE HumanResources.EmployeePayHistory
SET PayFrequency = 2 
WHERE CURRENT OF complex_cursor;
CLOSE complex_cursor;
DEALLOCATE complex_cursor;
GO

Festlegen von Spaltenwerten

Die Beispiele in diesem Abschnitt veranschaulichen die Aktualisierung von Spalten mithilfe von berechneten Werten, Unterabfragen und DEFAULT-Werten.

A. Angeben eines berechneten Werts

In den folgenden Beispielen werden berechnete Werte in einer UPDATE-Anweisung verwendet. In diesem Beispiel wird der Wert in der ListPrice-Spalte für alle Zeilen in der Product-Tabelle verdoppelt.

USE AdventureWorks2008R2 ;
GO
UPDATE Production.Product
SET ListPrice = ListPrice * 2;
GO

B. Angeben eines Verbundoperators

Im folgenden Beispiel wird die @NewPrice-Variable verwendet, um den Preis aller roten Fahrräder zu erhöhen, indem zum aktuellen Preis der Wert 10 addiert wird.

USE AdventureWorks2008R2;
GO
DECLARE @NewPrice int = 10;
UPDATE Production.Product
SET ListPrice += @NewPrice
WHERE Color = N'Red';
GO

Im folgenden Beispiel werden mithilfe des Verbundoperators += die ' - tool malfunction'-Daten an den vorhandenen Wert in der Spalte Name für Zeilen mit einer ScrapReasonID zwischen 10 und 12 angefügt.

USE AdventureWorks2008R2;
GO
UPDATE Production.ScrapReason 
SET Name += ' - tool malfunction'
WHERE ScrapReasonID BETWEEN 10 and 12;

C. Angeben einer Unterabfrage in der SET-Klausel

Im folgenden Beispiel wird mit einer Unterabfrage in der SET-Klausel der Wert bestimmt, der zum Aktualisieren der Spalte verwendet wird. Die Unterabfrage muss nur einen Skalarwert (d. h. einen einzelnen Wert pro Zeile) zurückgeben. In diesem Beispiel wird die Spalte SalesYTD in der SalesPerson-Tabelle geändert, um die neuesten Verkaufszahlen in der SalesOrderHeader-Tabelle wiederzugeben. Die Unterabfrage aggregiert die Umsätze für jeden Vertriebsmitarbeiter in der UPDATE-Anweisung.

USE AdventureWorks2008R2;
GO
UPDATE Sales.SalesPerson
SET SalesYTD = SalesYTD + 
    (SELECT SUM(so.SubTotal) 
     FROM Sales.SalesOrderHeader AS so
     WHERE so.OrderDate = (SELECT MAX(OrderDate)
                           FROM Sales.SalesOrderHeader AS so2
                           WHERE so2.SalesPersonID = so.SalesPersonID)
     AND Sales.SalesPerson.BusinessEntityID = so.SalesPersonID
     GROUP BY so.SalesPersonID);
GO

D. Aktualisieren von Zeilen mit DEFAULT-Werten

Im folgenden Beispiel wird die Spalte CostRate auf den Standardwert (0.00) für alle Zeilen festgelegt, die über einen CostRate-Wert größer als 20.00 verfügen.

USE AdventureWorks2008R2;
GO
UPDATE Production.Location
SET CostRate = DEFAULT
WHERE CostRate > 20.00;

Angeben von Zielobjekten, die keine Standardtabellen sind

In den Beispielen in diesem Abschnitt wird veranschaulicht, wie Zeilen durch Angeben einer Sicht, eines Tabellenalias oder einer Tabellenvariablen aktualisiert werden.

A. Angeben einer Sicht als Zielobjekt

Im folgenden Beispiel werden Zeilen in einer Tabelle aktualisiert, indem eine Sicht als Zielobjekt angegeben wird. Die Sichtdefinition verweist auf mehrere Tabellen, die UPDATE-Anweisung wird jedoch erfolgreich ausgeführt, da sie auf Spalten nur von einer der zugrunde liegenden Tabellen verweist. Die UPDATE-Anweisung würde fehlschlagen, wenn Spalten von beiden Tabellen angegeben wären. Weitere Informationen finden Sie unter Ändern von Daten über eine Sicht.

USE AdventureWorks2008R2;
GO
UPDATE Person.vStateProvinceCountryRegion
SET CountryRegionName = 'United States of America'
WHERE CountryRegionName = 'United States';

B. Angeben eines Tabellenalias als Zielobjekt

Im folgenden Beispiel werden Zeilen in der Tabelle Production.ScrapReason aktualisiert. Der ScrapReason in der FROM-Klausel zugewiesene Tabellenalias wird als Zielobjekt in der UPDATE-Klausel angegeben.

USE AdventureWorks2008R2;
GO
UPDATE sr
SET sr.Name += ' - tool malfunction'
FROM Production.ScrapReason AS sr
JOIN Production.WorkOrder AS wo 
     ON sr.ScrapReasonID = wo.ScrapReasonID
     AND wo.ScrappedQty > 300;

C. Angeben einer Tabellenvariablen als Zielobjekt

Im folgenden Beispiel werden Zeilen in einer Tabellenvariablen aktualisiert.

USE AdventureWorks2008R2;
GO
-- Create the table variable.
DECLARE @MyTableVar table(
    EmpID int NOT NULL,
    NewVacationHours int,
    ModifiedDate datetime);

-- Populate the table variable with employee ID values from HumanResources.Employee.
INSERT INTO @MyTableVar (EmpID)
    SELECT BusinessEntityID FROM HumanResources.Employee;

-- Update columns in the table variable.
UPDATE @MyTableVar
SET NewVacationHours = e.VacationHours + 20,
    ModifiedDate = GETDATE()
FROM HumanResources.Employee AS e 
WHERE e.BusinessEntityID = EmpID;

-- Display the results of the UPDATE statement.
SELECT EmpID, NewVacationHours, ModifiedDate FROM @MyTableVar
ORDER BY EmpID;
GO

Aktualisieren von Daten auf Grundlage von Daten aus anderen Tabellen

Anhand von Beispielen in diesem Abschnitt werden Methoden zum Aktualisieren von Zeilen auf Grundlage von Informationen in einer anderen Tabelle gezeigt.

A. Verwenden der UPDATE-Anweisung mit Informationen aus einer anderen Tabelle

Im folgenden Beispiel wird die SalesYTD in der SalesPerson-Tabelle geändert, um die neuesten Verkaufszahlen in der SalesOrderHeader-Tabelle wiederzugeben.

USE AdventureWorks2008R2;
GO
UPDATE Sales.SalesPerson
SET SalesYTD = SalesYTD + SubTotal
FROM Sales.SalesPerson AS sp
JOIN Sales.SalesOrderHeader AS so
    ON sp.BusinessEntityID = so.SalesPersonID
    AND so.OrderDate = (SELECT MAX(OrderDate)
                        FROM Sales.SalesOrderHeader
                        WHERE SalesPersonID = sp.BusinessEntityID);
GO

Im vorherigen Beispiel wird angenommen, dass nur ein Verkauf für einen angegebenen Verkäufer an einem bestimmten Datum aufgezeichnet wird und Aktualisierungen aktuell sind. Wenn mehr als ein Verkauf für einen angegebenen Verkäufer am selben Tag gespeichert werden kann, funktioniert das gezeigte Beispiel nicht richtig. Das Beispiel wird zwar fehlerlos ausgeführt, jeder SalesYTD -Wert wird jedoch mit nur einem Verkauf aktualisiert. Dies ist unabhängig davon, wie viele Verkäufe an diesem Tag tatsächlich stattgefunden haben. Die Ursache ist darin zu suchen, dass eine einzelne UPDATE-Anweisung dieselbe Zeile nicht zweimal ändern kann.

Wenn für einen angegebenen Vertriebsmitarbeiter mehrere Verkäufe pro Tag möglich sind, müssen sämtliche Verkäufe der einzelnen Vertriebsmitarbeiter mithilfe der UPDATE-Anweisung aggregiert werden, wie im nachfolgenden Beispiel dargestellt:

USE AdventureWorks2008R2;
GO
UPDATE Sales.SalesPerson
SET SalesYTD = SalesYTD + 
    (SELECT SUM(so.SubTotal) 
     FROM Sales.SalesOrderHeader AS so
     WHERE so.OrderDate = (SELECT MAX(OrderDate)
                           FROM Sales.SalesOrderHeader AS so2
                           WHERE so2.SalesPersonID = so.SalesPersonID)
     AND Sales.SalesPerson.BusinessEntityID = so.SalesPersonID
     GROUP BY so.SalesPersonID);
GO

Aktualisieren von Zeilen in einer Remotetabelle

In den Beispielen in diesem Abschnitt wird veranschaulicht, wie Zeilen in einer Remotezieltabelle mit einem Verbindungsserver oder einer Rowsetfunktion aktualisiert werden, um auf die Remotetabelle zu verweisen.

A. Aktualisieren von Daten in einer Remotetabelle mithilfe eines Verbindungsservers

Im folgenden Beispiel wird eine Tabelle auf einem Remoteserver aktualisiert. In diesem Beispiel wird zunächst mithilfe von sp_addlinkedserver ein Link zur Remotedatenquelle erstellt. Der Name des Verbindungsservers (MyLinkServer) wird anschließend als Teil des vierteiligen Objektnamens in der Form server.catalog.schema.object angegeben. Beachten Sie, dass Sie einen gültigen Servernamen für @datasrc angeben müssen.

USE master;
GO
-- Create a link to the remote data source. 
-- Specify a valid server name for @datasrc as 'server_name' or 'server_name\instance_name'.

EXEC sp_addlinkedserver @server = N'MyLinkServer',
    @srvproduct = N' ',
    @provider = N'SQLNCLI10', 
    @datasrc = N'<server name>',
    @catalog = N'AdventureWorks2008R2';
GO
USE AdventureWorks2008R2;
GO
-- Specify the remote data source using a four-part name 
-- in the form linked_server.catalog.schema.object.

UPDATE MyLinkServer.AdventureWorks.HumanResources.Department
SET GroupName = N'Public Relations'
WHERE DepartmentID = 4;

B. Aktualisieren von Daten in einer Remotetabelle mithilfe der OPENQUERY-Funktion

Im folgenden Beispiel wird durch Angabe der OPENQUERY-Rowsetfunktion eine Zeile in einer Remotetabelle aktualisiert. Der im vorherigen Beispiel erstellte Name des Verbindungsservers wird hier verwendet.

UPDATE OPENQUERY (MyLinkServer, 'SELECT GroupName FROM HumanResources.Department WHERE DepartmentID = 4') 
SET GroupName = 'Sales and Marketing';

C. Aktualisieren von Daten in einer Remotetabelle mithilfe der OPENDATASOURCE-Funktion

Im folgenden Beispiel wird durch Angabe der OPENDATASOURCE-Rowsetfunktion eine Zeile in eine Remotetabelle eingefügt. Geben Sie einen gültigen Servernamen für die Datenquelle im Format server_name oder server_name\instance_name an. Sie müssen die Instanz von SQL Server möglicherweise für verteilte Ad-hoc-Abfragen konfigurieren. Weitere Informationen finden Sie unter Ad Hoc Distributed Queries (Option).

UPDATE OPENQUERY (MyLinkServer, 'SELECT GroupName FROM HumanResources.Department WHERE DepartmentID = 4') 
SET GroupName = 'Sales and Marketing';

Aktualisieren von Large Object-Datentypen

Anhand von Beispielen in diesem Abschnitt werden Methoden zum Aktualisieren von Werten in Spalten gezeigt, die mit LOB-Datentypen (Large Object) definiert sind.

A. Verwenden von UPDATE mit .WRITE zum Ändern von Daten in einer nvarchar(max)-Spalte

Im folgenden Beispiel wird die .WRITE-Klausel verwendet, um einen Teilwert in DocumentSummary zu aktualisieren, einer nvarchar(max)-Spalte in der Production.Document -Tabelle. Das Wort components wird durch das Wort features ersetzt. Dazu werden das Ersetzungswort, die Anfangsposition (Offset) des zu ersetzenden Worts in den vorhandenen Daten und die Anzahl von zu ersetzenden Zeichen (Länge) angegeben. Im Beispiel wird außerdem die OUTPUT-Klausel zur Rückgabe der Anfangs- und Endimages der Spalte DocumentSummary an die @MyTableVar-Tabellenvariable verwendet.

USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table (
    SummaryBefore nvarchar(max),
    SummaryAfter nvarchar(max));
UPDATE Production.Document
SET DocumentSummary .WRITE (N'features',28,10)
OUTPUT deleted.DocumentSummary, 
       inserted.DocumentSummary 
    INTO @MyTableVar
WHERE Title = N'Front Reflector Bracket Installation';
SELECT SummaryBefore, SummaryAfter 
FROM @MyTableVar;
GO

B. Verwenden von UPDATE mit .WRITE zum Hinzufügen und Entfernen von Daten in einer nvarchar(max)-Spalte

In den folgenden Beispielen werden Daten einer nvarchar(max)-Spalte hinzugefügt bzw. daraus entfernt, die einen Wert hat, der zurzeit auf NULL festgelegt ist. Da die .WRITE-Klausel nicht zum Ändern einer NULL-Spalte verwendet werden kann, wird die Spalte zuerst mit temporären Daten aufgefüllt. Anschließend werden diese Daten mithilfe der .WRITE-Klausel durch die richtigen Daten ersetzt. In den zusätzlichen Beispielen werden am Ende des Spaltenwerts Daten angefügt, Daten aus der Spalte (durch Abschneiden) entfernt und schließlich Teildaten aus der Spalte entfernt. Die SELECT-Anweisungen zeigen die Datenänderung an, die von jeder UPDATE-Anweisung generiert wurde.

USE AdventureWorks2008R2;
GO
-- Replacing NULL value with temporary data.
UPDATE Production.Document
SET DocumentSummary = N'Replacing NULL value'
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
SELECT DocumentSummary 
FROM Production.Document
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
-- Replacing temporary data with the correct data. Setting @Length to NULL 
-- truncates all existing data from the @Offset position.
UPDATE Production.Document
SET DocumentSummary .WRITE(N'Carefully inspect and maintain the tires and crank arms.',0,NULL)
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
SELECT DocumentSummary 
FROM Production.Document
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
-- Appending additional data to the end of the column by setting 
-- @Offset to NULL.
UPDATE Production.Document
SET DocumentSummary .WRITE (N' Appending data to the end of the column.', NULL, 0)
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
SELECT DocumentSummary 
FROM Production.Document
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
-- Removing all data from @Offset to the end of the existing value by 
-- setting expression to NULL. 
UPDATE Production.Document
SET DocumentSummary .WRITE (NULL, 56, 0)
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
SELECT DocumentSummary 
FROM Production.Document
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
-- Removing partial data beginning at position 9 and ending at 
-- position 21.
UPDATE Production.Document
SET DocumentSummary .WRITE ('',9, 12)
WHERE Title = N'Crank Arm and Tire Maintenance';
GO
SELECT DocumentSummary 
FROM Production.Document
WHERE Title = N'Crank Arm and Tire Maintenance';
GO

C. Verwenden von UPDATE mit OPENROWSET zum Ändern einer varbinary(max)-Spalte

Im folgenden Beispiel wird ein vorhandenes Image, das in einer varbinary(max)-Spalte gespeichert ist, durch ein neues Image ersetzt. Die OPENROWSET-Funktion wird mit der BULK-Option verwendet, um das Image in die Spalte zu laden. In diesem Beispiel wird angenommen, dass eine Datei namens Tires.jpg im angegebenen Dateipfad vorhanden ist.

USE AdventureWorks2008R2;
GO
UPDATE Production.ProductPhoto
SET ThumbNailPhoto = (
    SELECT *
    FROM OPENROWSET(BULK 'c:\Tires.jpg', SINGLE_BLOB) AS x )
WHERE ProductPhotoID = 1;
GO

D. Verwenden von UPDATE zum Ändern von FILESTREAM-Daten

Im folgenden Beispiel wird die UPDATE-Anweisung zum Ändern der Daten in der Dateisystemdatei verwendet. Diese Methode wird nicht zum Streamen von großen Datenmengen in eine Datei empfohlen. Verwenden Sie die entsprechenden Win32-Schnittstellen. Im folgenden Beispiel wird der gesamte Text im Dateidatensatz durch den Text Xray 1 ersetzt. Weitere Informationen finden Sie unter Übersicht über FILESTREAM.

UPDATE Archive.dbo.Records
SET [Chart] = CAST('Xray 1' as varbinary(max))
WHERE [SerialNumber] = 2;

Aktualisieren benutzerdefinierter Typen

In den folgenden Beispielen werden Werte in Spalten eines CLR-benutzerdefinierten Typs (UDT) geändert. Es werden drei Methoden gezeigt. Weitere Informationen zu benutzerdefinierten Spalten finden Sie unter Benutzerdefinierte CLR-Typen.

A. Verwenden eines Systemdatentyps

Sie können einen UDT durch Bereitstellen eines Werts eines SQL Server-Systemdatentyps aktualisieren, sofern der benutzerdefinierte Typ implizite oder explizite Konvertierung von diesem Typ unterstützt. Im folgenden Beispiel wird gezeigt, wie Sie einen Wert in einer Spalte des benutzerdefinierten Typs Point durch explizites Konvertieren aus einer Zeichenfolge aktualisieren.

UPDATE dbo.Cities
SET Location = CONVERT(Point, '12.3:46.2')
WHERE Name = 'Anchorage';

B. Aufrufen einer Methode

Sie können einen UDT durch Aufrufen einer Methode des benutzerdefinierten Typs, die als Mutator markiert ist, aktualisieren, um die Aktualisierung auszuführen. Im folgenden Beispiel wird eine Mutatormethode des Typs Point namens SetXY aufgerufen. Dadurch wird der Status der Instanz des Typs aktualisiert.

UPDATE dbo.Cities
SET Location.SetXY(23.5, 23.5)
WHERE Name = 'Anchorage';

C. Ändern des Werts einer Eigenschaft oder eines Datenelements

Sie können einen UDT durch Ändern des Werts eines Elements einer registrierten Eigenschaft oder öffentlicher Daten des benutzerdefinierten Typs aktualisieren. Der Ausdruck, der den Wert bereitstellt, muss implizit in den Typ der Eigenschaft konvertierbar sein. Im folgenden Beispiel wird der Wert der X-Eigenschaft des benutzerdefinierten Typs Point geändert.

UPDATE dbo.Cities
SET Location.X = 23.5
WHERE Name = 'Anchorage';

Außerkraftsetzen des Standardverhaltens des Abfrageoptimierers mithilfe von Hinweisen

In den Beispielen in diesem Abschnitt wird gezeigt, wie mit Tabellen- und Abfragehinweisen beim Verarbeiten der UPDATE-Anweisung zeitweise das Standardverhalten des Abfrageoptimierers außer Kraft gesetzt wird.

VorsichtshinweisVorsicht

Da der SQL Server-Abfrageoptimierer in der Regel den optimalen Ausführungsplan für eine Abfrage auswählt, wird empfohlen, dass erfahrene Entwickler und Datenbankadministratoren Hinweise nur dann verwenden, wenn alle anderen Möglichkeiten sich als unzureichend erwiesen haben.

A. Angeben eines Tabellenhinweises

Im folgenden Beispiel wird der Tabellenhinweis TABLOCK angegeben. Dieser Hinweis gibt an, dass eine gemeinsame Sperre für die Tabelle Production.Product eingerichtet und bis zum Ende der UPDATE-Anweisung aufrechterhalten wird.

USE AdventureWorks2008R2;
GO
UPDATE Production.Product
WITH (TABLOCK)
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE 'BK-%';
GO

B. Angeben eines Abfragehinweises

Im folgenden Beispiel wird der AbfragehinweisOPTIMIZE FOR (@variable) in der UPDATE-Anweisung angegeben. Dieser Hinweis weist den Abfrageoptimierer an, einen bestimmten Wert für eine lokale Variable zu verwenden, wenn die Abfrage kompiliert und optimiert wird. Dieser Wert wird nur während der Abfrageoptimierung verwendet, nicht während der Abfrageausführung.

USE AdventureWorks2008R2;
GO
CREATE PROCEDURE Production.uspProductUpdate
@Product nvarchar(25)
AS
SET NOCOUNT ON;
UPDATE Production.Product
SET ListPrice = ListPrice * 1.10
WHERE ProductNumber LIKE @Product
OPTION (OPTIMIZE FOR (@Product = 'BK-%') );
GO
-- Execute the stored procedure 
EXEC Production.uspProductUpdate 'BK-%';

Erfassen der Ergebnisse der UPDATE-Anweisung

In den Beispielen in diesem Abschnitt wird gezeigt, wie mit der OUTPUT-Klausel Informationen aus jeder von einer UPDATE-Anweisung betroffenen Zeile bzw. Ausdrücke, die auf jeder Zeile basieren, zurückgegeben werden. Diese Ergebnisse können an die verarbeitende Anwendung zurückgegeben werden, die sie z. B. für Bestätigungen, Archivierungen und andere Anwendungsanforderungen verwendet.

A. Verwenden von UPDATE mit der OUTPUT-Klausel

Im folgenden Beispiel wird die Spalte VacationHours in der Tabelle Employee um 25 Prozent für die ersten 10 Zeilen aktualisiert und außerdem der Wert in der Spalte ModifiedDate auf das aktuelle Datum festgelegt. Die OUTPUT-Klausel gibt an die @MyTableVar-Tabellenvariable den Wert für VacationHours, der vor der Anwendung der UPDATE-Anweisung in der deleted.VacationHours-Spalte vorhanden war, und den aktualisierten Wert in der inserted.VacationHours-Spalte zurück.

Danach folgen zwei SELECT-Anweisungen, die die Werte in @MyTableVar sowie die Ergebnisse des Aktualisierungsvorgangs in der Employee-Tabelle zurückgeben. Weitere Beispiele zum Verwenden der OUTPUT-Klausel finden Sie unter OUTPUT-Klausel (Transact-SQL).

USE AdventureWorks2008R2;
GO
DECLARE @MyTableVar table(
    EmpID int NOT NULL,
    OldVacationHours int,
    NewVacationHours int,
    ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
    ModifiedDate = GETDATE() 
OUTPUT inserted.BusinessEntityID,
       deleted.VacationHours,
       inserted.VacationHours,
       inserted.ModifiedDate
INTO @MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM @MyTableVar;
GO
--Display the result set of the table.
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO

Verwenden von UPDATE in anderen Anweisungen

In Beispielen in diesem Abschnitt wird die Verwendung von UPDATE in anderen Anweisungen veranschaulicht.

A. Verwenden von UPDATE in einer gespeicherten Prozedur

Im folgenden Beispiel wird eine UPDATE-Anweisung in einer gespeicherten Prozedur verwendet. Die Prozedur erfordert den Eingabeparameter @NewHours und den Ausgabeparameter @RowCount. Der Parameterwert @NewHours wird in der UPDATE-Anweisung verwendet, um die Spalte VacationHours in der Tabelle HumanResources.Employee zu aktualisieren. Der Ausgabeparameter @RowCount wird verwendet, um die Anzahl betroffener Zeilen an eine lokale Variable zurückzugeben. Der CASE-Ausdruck wird in der SET-Klausel verwendet, um den Wert, der für VacationHours festgelegt wird, bedingt zu bestimmen. Wenn der Mitarbeiter pro Stunde bezahlt wird (SalariedFlag = 0), ist VacationHours auf die aktuelle Anzahl von Stunden zuzüglich des Werts festgelegt, der unter @NewHours angegeben ist. Andernfalls ist VacationHours auf den Wert festgelegt, der unter @NewHours angegeben ist.

USE AdventureWorks2008R2;
GO
CREATE PROCEDURE HumanResources.Update_VacationHours
@NewHours smallint
AS 
SET NOCOUNT ON;
UPDATE HumanResources.Employee
SET VacationHours = 
    ( CASE
         WHEN SalariedFlag = 0 THEN VacationHours + @NewHours
         ELSE @NewHours
       END
    )
WHERE CurrentFlag = 1;
GO

EXEC HumanResources.Update_VacationHours 40;

B. Verwenden von UPDATE in einem TRY…CATCH-Block

Im folgenden Beispiel wird eine UPDATE-Anweisung in einem TRY…CATCH-Block verwendet, um Ausführungsfehler zu behandeln, die während des Aktualisierungsvorgangs auftreten können. Weitere Informationen finden Sie unter Verwenden von TRY...CATCH in Transact-SQL.

USE AdventureWorks2008R2;
GO
BEGIN TRANSACTION;

BEGIN TRY
    -- Intentionally generate a constraint violation error.
    UPDATE HumanResources.Department
    SET Name = N'MyNewName'
    WHERE DepartmentID BETWEEN 1 AND 2;
END TRY
BEGIN CATCH
    SELECT 
         ERROR_NUMBER() AS ErrorNumber
        ,ERROR_SEVERITY() AS ErrorSeverity
        ,ERROR_STATE() AS ErrorState
        ,ERROR_PROCEDURE() AS ErrorProcedure
        ,ERROR_LINE() AS ErrorLine
        ,ERROR_MESSAGE() AS ErrorMessage;

    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
END CATCH;

IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO