You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-user@db.apache.org by Tim Dudgeon <td...@informaticsmatters.com> on 2013/12/20 20:54:45 UTC
Trigger questions
I'd like to check that my understanding of how triggers work is correct.
1. There is no procedural language like PL/SQL. The only solution here
is to use Java stored procedures.
2. Triggers can only execute a single statement. If you need to do
multiple things then you need to create multiple triggers (and in the
right order or execution).
3. Relating to this I'm finding something I didn't expect.
I create 2 triggers on a table:
create trigger trg1 after insert on tab ... for each row ...
create trigger trg2 after insert on tab ... for each row ...
Then I do an insert like this:
insert into tab ( ... ) values ( ... )
and the triggers seem to fire like this:
trg1, trg2
So far so good.
Now I do in insert like this:
insert into tab ( ... ) values ( ... ), ( ... ), ( ... )
and it seems the triggers fire like this:
trg1, trg1, trg1, trg2, trg2, trg2
I was expecting:
trg1, trg2, trg1, trg2, trg1, trg2
But what I really want is:
trg1, trg2
4. There is no way to have a single trigger that handles
insert/update/delete. You need multiple (potentially identical) triggers
p.s. What I'm wanting to achieve is to have trigger(s) on a table that
when an insert/update/delete operation occurs results in updating a
different table with a summary of the information for the modified row
and related rows (e.g averaging that row and all other rows with some
common attribute).
Many thanks
Tim
Re: Trigger questions
Posted by Tim Dudgeon <td...@informaticsmatters.com>.
OK, thanks for that. Its a big help.
I took a quick play with statement triggers and it looks like it might
be what I need.
That said my real need is a bit more complex than I made out, so I need
to work through it a bit more. I'll be back if (when?) I need more help!
Tim
On 23/12/2013 12:08, Knut Anders Hatlen wrote:
> Tim Dudgeon <td...@public.gmane.org> writes:
>
>> I'd like to check that my understanding of how triggers work is correct.
>>
>> 1. There is no procedural language like PL/SQL. The only solution here
>> is to use Java stored procedures.
>>
>> 2. Triggers can only execute a single statement. If you need to do
>> multiple things then you need to create multiple triggers (and in the
>> right order or execution).
>
> That's right. The SQL standard has syntax for multi-statement triggers,
> but Derby doesn't support that syntax yet. So stored procedures or
> multiple triggers are the alternatives for now.
>
>> 3. Relating to this I'm finding something I didn't expect.
>> I create 2 triggers on a table:
>> create trigger trg1 after insert on tab ... for each row ...
>> create trigger trg2 after insert on tab ... for each row ...
>>
>> Then I do an insert like this:
>> insert into tab ( ... ) values ( ... )
>>
>> and the triggers seem to fire like this:
>> trg1, trg2
>> So far so good.
>>
>> Now I do in insert like this:
>> insert into tab ( ... ) values ( ... ), ( ... ), ( ... )
>> and it seems the triggers fire like this:
>> trg1, trg1, trg1, trg2, trg2, trg2
>> I was expecting:
>> trg1, trg2, trg1, trg2, trg1, trg2
>
> I can see how that's not the expected behaviour, and it may be wrong. I
> did a quick check of what the SQL standard says on this, and I *think*
> Derby follows the letter of the standard here.
>
>> But what I really want is:
>> trg1, trg2
>
> Sounds like you want statement-level triggers instead of row-level
> triggers. That could be achieved by using FOR EACH STATEMENT instead of
> FOR EACH ROW in the CREATE TRIGGER statements.
>
>> 4. There is no way to have a single trigger that handles
>> insert/update/delete. You need multiple (potentially identical)
>> triggers
>
> Correct.
>
>> p.s. What I'm wanting to achieve is to have trigger(s) on a table that
>> when an insert/update/delete operation occurs results in updating a
>> different table with a summary of the information for the modified row
>> and related rows (e.g averaging that row and all other rows with some
>> common attribute).
>
> I think statement-level triggers should be able to do that job. It is
> possible to make the before and after image of the changed rows
> available to the trigger using a REFERENCING clause in the CREATE
> TRIGGER statement.
>
> For example, if you want every insert statement on MY_TABLE to be
> recorded in a table called CHANGES, with information about the number of
> rows inserted and the average value of the inserted rows, you could
> define a trigger similar to this one:
>
> CREATE TRIGGER tr AFTER INSERT ON my_table
> REFERENCING NEW TABLE AS NEW
> FOR EACH STATEMENT
> INSERT INTO changes(num_changed_rows, avg_value)
> SELECT COUNT(*), AVG(value) FROM NEW
>
>
> Hope this helps,
>
Re: Trigger questions
Posted by Knut Anders Hatlen <kn...@oracle.com>.
Tim Dudgeon <td...@informaticsmatters.com> writes:
> I'd like to check that my understanding of how triggers work is correct.
>
> 1. There is no procedural language like PL/SQL. The only solution here
> is to use Java stored procedures.
>
> 2. Triggers can only execute a single statement. If you need to do
> multiple things then you need to create multiple triggers (and in the
> right order or execution).
That's right. The SQL standard has syntax for multi-statement triggers,
but Derby doesn't support that syntax yet. So stored procedures or
multiple triggers are the alternatives for now.
> 3. Relating to this I'm finding something I didn't expect.
> I create 2 triggers on a table:
> create trigger trg1 after insert on tab ... for each row ...
> create trigger trg2 after insert on tab ... for each row ...
>
> Then I do an insert like this:
> insert into tab ( ... ) values ( ... )
>
> and the triggers seem to fire like this:
> trg1, trg2
> So far so good.
>
> Now I do in insert like this:
> insert into tab ( ... ) values ( ... ), ( ... ), ( ... )
> and it seems the triggers fire like this:
> trg1, trg1, trg1, trg2, trg2, trg2
> I was expecting:
> trg1, trg2, trg1, trg2, trg1, trg2
I can see how that's not the expected behaviour, and it may be wrong. I
did a quick check of what the SQL standard says on this, and I *think*
Derby follows the letter of the standard here.
> But what I really want is:
> trg1, trg2
Sounds like you want statement-level triggers instead of row-level
triggers. That could be achieved by using FOR EACH STATEMENT instead of
FOR EACH ROW in the CREATE TRIGGER statements.
> 4. There is no way to have a single trigger that handles
> insert/update/delete. You need multiple (potentially identical)
> triggers
Correct.
> p.s. What I'm wanting to achieve is to have trigger(s) on a table that
> when an insert/update/delete operation occurs results in updating a
> different table with a summary of the information for the modified row
> and related rows (e.g averaging that row and all other rows with some
> common attribute).
I think statement-level triggers should be able to do that job. It is
possible to make the before and after image of the changed rows
available to the trigger using a REFERENCING clause in the CREATE
TRIGGER statement.
For example, if you want every insert statement on MY_TABLE to be
recorded in a table called CHANGES, with information about the number of
rows inserted and the average value of the inserted rows, you could
define a trigger similar to this one:
CREATE TRIGGER tr AFTER INSERT ON my_table
REFERENCING NEW TABLE AS NEW
FOR EACH STATEMENT
INSERT INTO changes(num_changed_rows, avg_value)
SELECT COUNT(*), AVG(value) FROM NEW
Hope this helps,
--
Knut Anders