Delphi 火鸟去激活触发器

Delphi 火鸟去激活触发器,delphi,firebird,Delphi,Firebird,我有客户-->|级联规则-->订单|表-->|级联规则-->订单|详细信息 在我的订单详细信息中,我有一个删除后触发器,用于增加我的产品表中的数量 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

我有客户-->|级联规则-->订单|表-->|级联规则-->订单|详细信息 在我的订单详细信息中,我有一个删除后触发器,用于增加我的产品表中的数量

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
如果我删除了一个客户,那么所有与之相关的订单都将被删除 订单和细节等等

问题是,delete触发器之后的order_details将被触发,并增加产品数量,我不希望发生这种情况

我的问题:有没有办法知道触发器是由来自应用程序的级联规则或sql delete语句触发的

我想实现以下目标:


如果触发器由级联规则触发,则禁用所有触发器。提前感谢您的帮助。

您无法确定这一点,但可以确定您的外键是否仍然有效。由于Firebird级联删除是按顺序进行的(外键中引用的行首先被删除),因此在更新记录之前,您可以检查您的
旧.id\u文章是否仍然有效。

我不确定您是否能达到您想要的效果。如果您只是删除一个订单及其项目会怎么样。在这种情况下,你不想增加数量吗

无论如何。。。我不会从触发器内部停用触发器。这是个糟糕的设计

使用某种变量。。。更新支持表中的标志。在客户端删除触发器中,可以设置此变量。然后在order_items delete触发器中,您可以检查它以查看是否需要更新数量

另一个更好的选择是更好地分析情况,并确定您实际想要更新数量的原因和时间。如果您要删除一个已经完成并交付的旧订单,您可能不想这样做。如果你要取消一个新订单,你可能会。因此,更新数量实际上更多地取决于订单(或其他变量)的状态,而不仅仅取决于您正在删除订单项目行


好的,你说订单不能被删除,除非在删除客户机时。然后,也许您应该用一个表明客户机正在被删除的标志来标记客户机或其订单。在order_items delete触发器中,仅当客户端未被删除时,您才更新物品数量。

您可以尝试使用execute语句将删除代码包装到存储过程中,以便在触发器中/激活触发器

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^

我最终在我的clients表中使用上下文变量,我在delete触发器之后添加,并使用
rdb$set\u 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 ; ^
在详细顺序中,我使用
rdb$get_context
检查我的标志,如果标志与相关值存在,则跳过触发器

select rdb$get_context('USER_SESSION', 'myvar') from rdb$database into :i;
if (i = 100) then exit;

我想你误解了这个问题触发工作正常谢谢我的应用程序中的@Frazz订单不能删除,只能取消并作为取消订单存档,但是如果你想在我的情况下删除/插入/更新项目如果用户想删除客户,那么没有客户的订单就很奇怪!!如果我依赖firebird依赖项,则数量将增加,就好像我希望摆脱客户返回的产品以及所有与之相关的产品,而不影响数量一样。我认为,禁用触发器不是一个选项。我严重怀疑你能在一个事务中做到这一点,而其他事务却一直激活触发器。触发器用于数据完整性,应视为常量。我意识到可能需要停用触发器的唯一时刻是在执行维护脚本或类似脚本时。这应该在数据库对用户和应用程序离线时完成。有了您提供的新信息,我将更新我的答案。也许您可以使用和来实现这一点。我想我将使用此解决方案我将设置所有规则为“无操作”,并使用存储过程创建我自己的引用完整性我强烈建议不要使用此选项:这可能会禁用所有用户的触发器!正如@Mark在最初的评论中所说,使用上下文变量是一个非常重要的问题。当您启动事务时,您的过程将设置一个上下文变量,在触发器中,您将检查该上下文变量,如果该变量处于某个特定值,则跳过所需内容。@s.FATEH是的,但可能会影响多个数据库连接,每个连接都会受到影响。您好。我缺少一些内容,但上面的代码与“execute block”不兼容