2014-04-13 6 views
5

Problem: Ein möglichst einfacher Aktualisierungstrigger schreibt einen neuen Wert in alle Tabellenzeilen und nicht nur in die Zeile, die aktualisiert wird. Hier ist die Tabelle:SQLite-Aktualisierungstrigger ändert alle Zeilen in der Tabelle

[Namen]

id INTEGER PRIMARY KEY 
name TEXT 
len INTEGER 

Jetzt möchte ich Trigger erstellen aktualisieren 'len' mit der Länge von 'name'. Dieser INSERT-Trigger scheint corectly, den Job zu:

CREATE TRIGGER 'namelen' AFTER INSERT ON 'names' 
BEGIN 
UPDATE 'names' SET len = length(NEW.name) WHERE (id=NEW.id); 
END; 

Probleme beginnen, wenn ich einen ähnlichen UPDATE-Trigger hinzufügen:

CREATE TRIGGER 'namelenupd' AFTER UPDATE ON 'names' 
BEGIN 
UPDATE 'names' SET len = length(NEW.name) WHERE (OLD.id=NEW.id); 
END; 

Die Update-Trigger die neue Länge zu alle Zeilen der Tabelle schreiben , trotz der WHERE-Klausel. wenn ich sage, zum Beispiel

UPDATE 'names' SET name='foo' where id=1; 

dann wird der Wert von ‚len‘ wird 3 für alle Zeilen der Tabelle. Ich habe sqlite Trigger-Beispiele angeschaut und kann meinen Fehler nicht sehen. Was muss ich noch tun, um sicherzustellen, dass der Trigger die 'len' Spalte aktualisiert nur in den Zeilen, die tatsächlich aktualisiert werden?

+0

haben Sie versucht ** UPDATE SET 'Namen' len = Länge (NEW.name) WHERE (id = OLD.id); ** – sqlab

+0

Wie haben Sie dieses Problem beheben? – Anima

Antwort

9

Sowohl OLD.xxx als auch NEW.xxx verweisen auf die Tabellenzeile, die den Trigger ausgelöst hat. Die UPDATE-Anweisung im Trigger wird unabhängig ausgeführt. Wenn Sie es auf eine Tabellenzeile beschränken möchten, müssen Sie dies explizit in der WHERE-Klausel tun, indem Sie die Tabellenwerte der Anweisung filtern, d. h. names.id oder nur id.

Wenn die ursprüngliche Anweisung UPDATE nicht die id Spalte ändern, die alten und neuen id Werte gleich sind, und der Ausdruck OLD.id=NEW.id ist für alle Datensätze in der Tabelle wahr, wie durch die innere Anweisung UPDATE gesehen.

Die richtigen Auslöser wie folgt aussehen:

CREATE TRIGGER "namelenupd" 
AFTER UPDATE OF name ON "names" 
BEGIN 
    UPDATE "names" SET len = length(NEW.name) WHERE id = NEW.id; 
END; 
+0

Wenn die ursprüngliche UPDATE-Anweisung die ID nicht ändert, dann ist id = NEW.id für alle Zeilen wahr, richtig? – Anima

+0

@Amina Nein; 'id' hat für jede Zeile einen anderen Wert, aber 'NEW.id' ist ein * einzelner * Wert während einer Ausführung des Triggers. –

+0

aah ich sehe. Danke!! – Anima

0

das gleiche Problem, hier haben die Syntax von meinem Stecher

Sie würden „ALTEN“ auf „CREATE“, je nachdem, was Sie bereits haben (oder nicht)

Sie haben "id" als primäre Schlüssel

Ihre dbo ist "names"

Offensichtlich wird dies den Namen Wert auf "foo" setzen (nicht wirklich, was Sie wollten). Der Schlüssel scheint die letzte Zeile zu sein, in der Sie inner join inserted on names.Id = inserted.Id setzen.

USE [yourDBname] 
    ALTER TRIGGER [dbo].[yourTrigger] 
     ON [dbo].[names] 
     After INSERT, UPDATE 
    AS 

    BEGIN 
     -- SET NOCOUNT ON added to prevent extra result sets from 
     -- interfering with SELECT statements. 
     SET NOCOUNT ON; 

    Select id from inserted 
     begin 
     update [dbo].names 
      set [dbo].names.name = 'foo' 
      from dbo.names 
       inner join inserted 
       on names.id = inserted.id 
     END 
+0

SQLite hat keinen USE- oder ALTER-TRIGGER. –

+0

@CL kleine Verwendung von Down-Abstimmung. – Terri

+0

Bei einer Frage zu SQLite ist diese Antwort überhaupt nicht nützlich *. Genau dafür sind Downvotes gedacht. –

Verwandte Themen