Question

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.

Was it helpful?

Solution 2

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;

OTHER TIPS

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^

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top