Reputation: 451
I have clients-->|cascade rule|-->orders_table-->|cascade rule|-->order_details in my order_details I have after delete trigger that increment the quantity in my product table
CREATE OR ALTER TRIGGER TABLEAU_DETAIL_VENTES_AD0 FOR TABLEAU_DETAIL_VENTES
ACTIVE AFTER DELETE POSITION 0
AS
declare variable qte numeric_15_2;
begin
select qte_article from tableau_articles where id_article = old.id_article
into :qte;
qte = :qte + old.qte;
update tableau_articles
set qte_article = :qte
where id_article = old.id_article;
end
If I delete a client than all orders depending on it will be deleted and the orders_detail so on.
The problem is that order_details after delete trigger will be fired and incrementing the product quantity I don't want that to happen.
My question: is there any way to know if the trigger has been fired by cascade rule or sql delete statement that come from the application?
I want to achieve something like:
If trigger triggered by the cascade rule then disable_all_triggers. Thanks in advance for your help.
Upvotes: 3
Views: 3370
Reputation: 451
I end up using context variables in my clients table i add after delete trigger and set a flag using rdb$set_context
SET TERM ^ ;
CREATE OR ALTER TRIGGER TABLEAU_CLIENTS_AD0 FOR TABLEAU_CLIENTS
ACTIVE AFTER DELETE POSITION 0
AS
declare variable id integer;
begin
execute statement 'select rdb$set_context(''USER_SESSION'', ''myvar'', 100) from rdb$database' into :id;
end
^
SET TERM ; ^
in the detail orders i check my flag with rdb$get_context
and skip the trigger if the flag exist with the value associated
select rdb$get_context('USER_SESSION', 'myvar') from rdb$database into :i;
if (i = 100) then exit;
Upvotes: 3
Reputation: 597
You can try to wrap your delete code in stored procedure with execute statement for in/activate the trigers
CREATE PROCEDURE DeleteClient(
ID INTEGER)
AS
begin
execute statement 'alter trigger TABLEAU_DETAIL_VENTES_AD0 inactive;';
/*
Your Delete statement here
*/
execute statement 'alter trigger TABLEAU_DETAIL_VENTES_AD0 active;';
END^
Upvotes: 3
Reputation: 3043
I'm not sure you would achieve what you want like that. What if you just delete an order and its items. Wouldn't you want to increment quantities in that case?
Anyway... I wouldn't deactivate triggers from within triggers. That is bad design.
Use some sort of variable... update a flag in a support table. From within the client delete trigger you can set this variable. Then in the order_items delete trigger you can check it to see if you need to update quantities.
Another better option is to analyze the situation better and determine why and when you actually want to update quantities. If you are deleting an old order which has already been fulfilled and delivered, you probably wouldn't want to. If you are canceling a new order, you probably would. So maybe updating the quantities depends actually more on the state of the order (or some other variable) then simply on the fact that you are deleting an order_items row.
Ok, so you say orders cannot be deleted, except when deleting the client. Then maybe you should flag the client or its order with a flag that states the client is being deleted. In the order_items delete trigger you update article quantities only if the client is not being deleted.
Upvotes: 0
Reputation: 1154
You can't determine that, but you can determine if your foreign key is still valid. Since Firebird cascaded deletes are sequential (rows that are referenced in a foreign keys are deleted first), you can check if your old.id_article
is still valid before updating the record.
Upvotes: 0