T-SQL: Verwenden eines CASE in einer UPDATE-Anweisung zum Aktualisieren bestimmter Spalten in Abhängigkeit von einer Bedingung

107

Ich frage mich, ob das überhaupt möglich ist. Ich möchte Spalte x aktualisieren, wenn eine Bedingung erfüllt ist, andernfalls würde Spalte y aktualisiert

UPDATE table SET
     (CASE (CONDITION) WHEN TRUE THEN columnx
                       ELSE columny
      END)
= 25

Ich habe überall gesucht, einige Dinge ausprobiert und kann keine Lösung finden. Ich denke, es ist nicht möglich, aber ich dachte, ich würde hier fragen und sehen, ob es schon jemand getan hat. Danke im Voraus.

pqsk
quelle
Angenommen, alle in derselben Tabelle, ja. Sie können es jederzeit in einer Transaktion ausführen und bei einem Fehler zurücksetzen, um sich selbst davon zu überzeugen.
OMG Ponys
Ich bin mir nicht sicher was du meinst. Ich habe versucht, eine Bedingung für die Spalte zu setzen, aber es funktioniert nicht. Es funktioniert für eine select-Anweisung, aber nicht für eine Update-Anweisung (select (case (Bedingung), wenn true, dann columnx else columny end) aus myTable .... das Update funktioniert nicht, und ich kann sehen, warum. Es scheint kein Weg zu sein, das zum
Laufen

Antworten:

188

Sie können keine Bedingung verwenden, um die Struktur Ihrer Abfrage zu ändern, sondern nur die beteiligten Daten. Sie könnten dies tun:

update table set
    columnx = (case when condition then 25 else columnx end),
    columny = (case when condition then columny else 25 end)

Dies ist semantisch gleich, aber denken Sie daran, dass beide Spalten immer aktualisiert werden . Dies wird Ihnen wahrscheinlich keine Probleme bereiten. Wenn Sie jedoch ein hohes Transaktionsvolumen haben, kann dies zu Parallelitätsproblemen führen.

Die einzige Möglichkeit, genau das zu tun, was Sie verlangen, ist die Verwendung von dynamischem SQL. Dies ist jedoch etwas, von dem ich Sie ermutigen würde, sich fernzuhalten. Die obige Lösung wird mit ziemlicher Sicherheit für das ausreichen, wonach Sie suchen.

Adam Robinson
quelle
Ich stimme dem dynamischen SQL zu. Werden meine Daten jedoch betroffen sein? Ich meine, ich möchte nicht, dass es für bestimmte Bedingungen geändert wird. Also wird einfach wieder eingefügt, was bereits drin ist? Die Anzahl der Treffer für die Datenbank ist möglicherweise nicht so schlecht.
pqsk
@pqsk: Dies sollte sich nicht auf Ihre Daten auswirken, sondern nur erneut einfügen, was bereits vorhanden ist, für welche Spalte auch immer nicht betroffen sein soll.
Adam Robinson
Vielen Dank. Ich werde damit gehen. So einfach kann es sogar ein Höhlenmensch. Haha.
pqsk
1
@AdamRobinson 1,5 Jahre sind vergangen. Kennen Sie eine effizientere Möglichkeit, nur eine Spalte zu aktualisieren
@Somebodyisintrouble: Die einzige Möglichkeit, eine Spalte zu aktualisieren, besteht darin, eine andere Abfrage zu verwenden.
Adam Robinson
23
UPDATE  table
SET     columnx = CASE WHEN condition THEN 25 ELSE columnx END,
        columny = CASE WHEN condition THEN columny ELSE 25 END
Quassnoi
quelle
1
Hast du gerade Adams Antwort kopiert oder wurde sie von woanders genommen? Haha. Hab das gerade bemerkt.
pqsk
1
@pqsk: Unsere Antworten waren ~ 1 Minute auseinander, also würde ich mir vorstellen, dass ich nur etwas schneller auf Senden geklickt habe;)
Adam Robinson
23
@pqsk: Ja, ich habe gerade Adams Antwort kopiert, 23Sekunden bevor er sie gepostet hat. Ich bin ein schneller Copypaster!
Quassnoi
2
@pqsk: Wenn Sie den Mauszeiger über das bewegen * min ago, wird die genaue Uhrzeit der Veröffentlichung angezeigt .
Quassnoi
2
Um fair zu sein, obwohl beide gleich sind: Wenn Adams nach Ihrem herausgekommen wäre, hat er noch etwas näher ausgeführt. Deshalb habe ich seine als Antwort markiert. Trotzdem danke.
pqsk
4

Geben Sie hier die Bildbeschreibung ein

Ich möchte meine ContactNo auf 8018070999 ändern oder aktualisieren, wobei 8018070777 mithilfe der Case-Anweisung vorhanden ist

update [Contacts] set contactNo=(case 
when contactNo=8018070777 then 8018070999
else
contactNo
end)

Geben Sie hier die Bildbeschreibung ein

Debendra Dash
quelle
1
Verwenden Sie dazu diese Abfrage. UPDATE [Kontakte] SET contactNo = 8018070999 WHERE contactNo = 8018070777
NewGuy
4

Ich weiß, dass dies eine sehr alte Frage ist, aber das hat bei mir funktioniert:

UPDATE TABLE SET FIELD1 =
CASE 
WHEN FIELD1 = Condition1 THEN 'Result1'
WHEN FIELD1 = Condition2 THEN 'Result2'
WHEN FIELD1 = Condition3 THEN 'Result3'
END;

Grüße

Victor Eduardo Salazar Ramirez
quelle
1

Ich weiß, dass dies eine sehr alte Frage ist und das Problem als behoben markiert ist. Wenn jedoch jemand in einem Fall wie dem meinen einen Auslöser für die Datenprotokollierung bei Aktualisierungsereignissen hat, führt dies zu Problemen. Beide Spalten erhalten das Update und das Protokoll macht unbrauchbare Einträge. So wie ich es gemacht habe

IF (CONDITION) IS TRUE
BEGIN
    UPDATE table SET columnx = 25
END
ELSE
BEGIN
    UPDATE table SET columny = 25
END

Dies hat einen weiteren Vorteil: Es werden keine unnötigen Schreibvorgänge wie bei den obigen Lösungen in die Tabelle aufgenommen.

Hart
quelle
Das ist ein guter Punkt und eine gute Alternative! Ich arbeite nicht mehr an dem ursprünglichen Code, der zu diesem Thread geführt hat, aber es ist immer gut, unterschiedliche Lösungen zu haben, und ich denke, dies ist eine gute Lösung
pqsk
-1

Ich glaube, dass Sie die Aktualisierung der "unerwünschten" Spalten unterlassen können, indem Sie die anderen Antworten wie folgt anpassen:
update table set columnx = (case when condition1 then 25 end), columny = (case when condition2 then 25 end)

Soweit ich weiß, wird dies nur aktualisiert, wenn die Bedingung erfüllt ist.

Nachdem Sie alle Kommentare gelesen haben, ist dies am effizientesten:
Update table set ColumnX = 25 where Condition1 Update table set ColumnY = 25 where Condition1

Beispieltabelle:
CREATE TABLE [dbo].[tblTest]( [ColX] [int] NULL, [ColY] [int] NULL, [ColConditional] [bit] NULL, [id] [int] IDENTITY(1,1) NOT NULL ) ON [PRIMARY]
Beispieldaten:
Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (1, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (2, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 1, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 2, null)

Nun gehe ich davon aus, dass Sie eine Bedingung schreiben können, die Nullen behandelt. In meinem Beispiel gehe ich davon aus, dass Sie eine solche Bedingung geschrieben haben, die True, False oder Null ergibt. Wenn Sie dabei Hilfe benötigen, lassen Sie es mich wissen und ich werde mein Bestes geben.

Wenn Sie nun diese beiden Codezeilen ausführen, ändert sich X genau dann auf 25, wenn ColConditional True (1) und Y auf 25 genau dann, wenn ColConditional False (0) ist.

Update tblTest set ColX = 25 where ColConditional = 1 Update tblTest set ColY = 25 where ColConditional = 0

PS Der Nullfall wurde in der ursprünglichen Frage oder in Aktualisierungen der Frage nie erwähnt, aber wie Sie sehen können, behandelt diese sehr einfache Antwort sie trotzdem.

John Greiner
quelle
1
Das funktioniert eigentlich nicht. Wenn die Spalte Nullen zulässt, wird zum einen ein Nullwert zugewiesen, wenn die Bedingung nicht erfüllt ist. Wenn Nullen nicht zulässig sind, schlägt die Aktualisierung fehl. Ihre letzte "effiziente" Abfrage ist ungültiges SQL, zumindest in TSQL. Haben Sie dies an einem bestimmten Motor getestet und es hat bei Ihnen funktioniert?
pqsk
Ich habe dies auf SQL Server 2005 getestet und es funktioniert perfekt wie gezeigt. Ich würde gerne wissen, warum es abgelehnt wurde und ein Beispiel, das zeigt, wie der NULL-Wert aktualisiert wird, da in meinem obigen Test der Nullwert nicht aktualisiert wird. Ich habe immer gedacht, dass die einfachste Antwort die beste ist, und wenn ich es mit einer Datenbank mit Millionen von Datensätzen zu tun habe, möchte ich auf keinen Fall unnötige Zeilen aktualisieren.
John Greiner