On Fri, Mar 09, 2012 at 09:49:22AM +1100, BareFeetWare wrote:
> I suggest only using "insert or replace" if you genuinely want to delete and 
> replace with a new row. This is generally not hat you want if there are any 
> foreign keys.
> 
> Only use "insert or ignore" if you are inserting exactly the same row as what 
> might already be there.
> 
> Otherwise use a combination of insert and update.
> 
> So, for example, if you are wanting to add a person that may not already be 
> in your table:
> 
> insert or ignore into "Person" ("First Name", "Last Name", "Company", "Email")
> select 'Tom', 'Brodhurst-Hill', 'BareFeetWare', 'develo...@barefeetware.com')
> ;
> update "Person"
> set "Email" = 'develo...@barefeetware.com'
> where "First Name" = 'Tom' and "Last Name" = 'Brodhurst-Hill'
> ;

I've had a similar problem in the past, and solved it by using a pre-insert
trigger to do the desired update.

Thus, the insert/update from above becomes just an insert (or ignore),
with an implied update in the trigger, which appears to be sematically
closer to what people want in the above case (though not in the original
subject matter.)

In my case, it was inserting "event" data if not already existing, else
updating an existing event record from the new event data (such as incrementing
an event count and updating timestamps):

        create table events (
                identifier text primary key,
                count integer default 1,
                firstoccurrence date not null,
                lastoccurrence date not null,
                <other fields>....
        );

        create trigger event_dedup
        before insert on events
        for each row
        begin
                update events set count=count+1, 
lastoccurrence=NEW.lastoccurrence where identifier=NEW.identifier;
        end;

        insert or ignore into events 
(identifier,firstoccurrence,lastoccurrence) values ('Some event 
1',datetime('now'),datetime('now'));
        insert or ignore into events 
(identifier,firstoccurrence,lastoccurrence) values ('Some event 
2',datetime('now'),datetime('now'));
        insert or ignore into events 
(identifier,firstoccurrence,lastoccurrence) values ('Some event 
1',datetime('now'),datetime('now'));
        <pause>
        insert or ignore into events 
(identifier,firstoccurrence,lastoccurrence) values ('Some event 
1',datetime('now'),datetime('now'));
        insert or ignore into events 
(identifier,firstoccurrence,lastoccurrence) values ('Some event 
2',datetime('now'),datetime('now'));
        insert or ignore into events 
(identifier,firstoccurrence,lastoccurrence) values ('Some event 
1',datetime('now'),datetime('now'));

        select * from events;
        Some event 1|4|2012-03-12 13:34:43|2012-03-12 13:34:48|...
        Some event 2|2|2012-03-12 13:34:43|2012-03-12 13:34:48|...

It must be noted as well that the above "select or ignore" data can be
generated from a select, so in the original question, the "update" could
be written as:

        insert or ignore into t1 ( tid, a, b ) select t1.tid, t1.a+t2.a, 
t1.b+t2.b from t1 join t2 on (t1.tid=t2.tid);

So long as the update in the pre-insert trigger updates all the required
fields. The select with join is only evaluated once, so will be more
efficient if the join was the dominant performance bottleneck, and emulates
the "update from select" noted in oracle elsewhere in the thread.

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

Reply via email to