On Tue, Mar 29, 2011 at 11:32 AM, Simon Slavin <slav...@bigfraud.org> wrote:
> On 29 Mar 2011, at 4:12pm, Sutter, Doug wrote:
>> I know how to create a unique trigger for each column where I hard-code
>> the column's name as shown below.  But I would like to create a trigger
>> that would fire when any column is updated and log the specific details
>> for that column only.
>
> You can compare the old and new values for any column you name 
> (old.columnName and new.columnName) but a single UPDATE command can change 
> any number of columns, so you would have to specifically test for each column 
> inside your TRIGGER, something like
>
> CREATE TRIGGER myTabUpdated
>    AFTER UPDATE OF myTab
>    FOR EACH ROW BEGIN
>    IF old.name <> new.name THEN
>        INSERT INTO changeLog ...;
>    IF old.address <> new.address THEN
>        INSERT INTO changeLog ...;
>    ...
>  END;
>
> Except that there is no such command as 'IF' in SQL.  Each TRIGGER can have 
> only one conditional: a WHEN clause that can go before the BEGIN.

The way to handle the absence of IF here is this:

CREATE TRIGGER ...
BEGIN
  INSERT INTO changeLog SELECT ... WHERE OLD.name IS NOT NEW.name;
  -- or
  INSERT INTO changeLog SELECT ... WHERE OLD.name IS NOT NEW.name AND ...;
  ...
END;

The trick is that you use an INSERT...SELECT/UPDATE/DELETE statement
with a WHERE clause where a conjunction with an expression unrelated
to the row being inserted/updated/deleted is used.  That expression is
likely, and certainly can be, completely unrelated to the rows being
inserted/updated/deleted -- but it should be related to the event that
triggered the trigger.

Sure, you can get a very similar effect with a WHEN clause on a
trigger, but a) you'll need more triggers, b) you get a fairly
artificial constraint on the log schema (OK, not really, but it
requires clever trigger body writing to make the WHEN approach not
constrain the log schema), c) using a WHEN clause is an uncomfortable
straightjacket compared to using WHERE clauses on the
INSERT/UPDATE/DELETE statements in the trigger body.

> You might be able to use CASE to do what you want but you will still need to 
> use several statements in a row, and I'm drawing a blank right now on how it 
> could be done.

You can't have an INSERT/UPDATE/DELETE embedded in a larger SELECT,
which means that you can't use CASE for making conditional changes.
The way to make conditional changes is with WHERE clauses (see above)
(or do it at the application layer, of course).

Nico
--
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to