【问题标题】:Firebird Trigger SQL Validate QueryFirebird 触发 SQL 验证查询
【发布时间】:2016-03-09 19:16:53
【问题描述】:

比较简单的问题。我正在尝试在调整 firebird 触发器上的 INSERT 值之前执行语句并检查值。我已经看到了许多示例,其中评估了新值,然后执行了后续语句,但没有我想要的。更容易显示...

SET TERM ^ ;
CREATE TRIGGER STOP_PREMIX_INSERT_PRODUCEDD FOR PRODUCEDD ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS 
BEGIN
    IF ('SELECT COUNT(*) FROM RECIPESTEPS rs INNER JOIN RECIPES r on r.RECIPEID=rs.RECIPEID INNER JOIN PRODUCEDH h on h.RECIPEID=r.RECIPEID WHERE h.BATCHID=' || new.BATCHID || ' AND ' || new.SEQUENCENO || '=rs.SEQUENCENO AND ' || new.COMMODITYID || '=rs.COMMODITYID AND rs.NONWEIGHED=17;' > 0) then
    new.BATCHID=-1;
END^
SET TERM ; ^

在对新条目执行值更改之前,我正在尝试验证另一个表中是否存在一条数据。

通常 IF (new.ID = 0) 然后执行语句 'blah';会起作用,但是当我编写此触发器时,它在语法上被接受,但是当值更改时,我收到以下错误消息:

算术异常、数值溢出或字符串截断 字符串右截断 在触发 'STOP_PREMIX_INSERT_PRODUCECEDD' 行:6,列:5

我可能是一个分号,或者这可能是不可能的,无论哪种方式,任何帮助表示赞赏。

【问题讨论】:

  • 我不知道 Firebird,但看起来您正在检查 SQL 字符串是否大于零。也许您需要执行字符串并比较结果?

标签: sql triggers firebird ddl


【解决方案1】:

它不起作用的原因是因为您正在构造一个字符串,然后将它与一个整数进行比较。结果转换失败。事实上,字符串包含一些看起来像 SQL 的东西,实际上并没有执行它。

您需要执行查询,例如使用EXISTS

SET TERM ^ ;
CREATE TRIGGER STOP_PREMIX_INSERT_PRODUCEDD FOR PRODUCEDD ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS 
BEGIN
    IF (EXISTS (SELECT * 
                FROM RECIPESTEPS rs 
                INNER JOIN RECIPES r on r.RECIPEID=rs.RECIPEID 
                INNER JOIN PRODUCEDH h on h.RECIPEID=r.RECIPEID 
                WHERE h.BATCHID = new.BATCHID 
                AND rs.SEQUENCENO = new.SEQUENCENO
                AND rs.COMMODITYID = new.COMMODITYID
                AND rs.NONWEIGHED = 17)) then
      new.BATCHID=-1;
END^
SET TERM ; ^

这可能比另一个答案中的 select count(*) 更高效,因为 Firebird 不需要查询所有行,只需检查是否有一个或多个。

【讨论】:

  • 感谢您的回复。我最初尝试了这条路线,但不幸的是,Firebird 似乎不支持 EXISTS 子句,因此我选择了 COUNT 路线。
  • @MxMave 我不确定你的意思,Firebird 确​​实支持exists,并且还支持如上所示的 PSQL。
  • 抱歉,你是对的。我在某个阶段遇到了未知的术语 EXISTS,一定是我的结构导致了这个问题。这会正确执行。
【解决方案2】:

应该是这样的:

SET TERM ^ ;
CREATE TRIGGER STOP_PREMIX_INSERT_PRODUCEDD FOR PRODUCEDD ACTIVE
BEFORE INSERT OR UPDATE POSITION 0
AS 
  declare variable CNT integer;
BEGIN
    SELECT COUNT(*) FROM RECIPESTEPS rs INNER JOIN RECIPES r on r.RECIPEID=rs.RECIPEID INNER JOIN PRODUCEDH h on h.RECIPEID=r.RECIPEID WHERE h.BATCHID = new.BATCHID AND new.SEQUENCENO = rs.SEQUENCENO AND  new.COMMODITYID = rs.COMMODITYID AND rs.NONWEIGHED=17 into :CNT;
    IF (CNT > 0) then
        new.BATCHID=-1;
END^
SET TERM ; ^

我无法检查它是否会工作,因为我没有您的数据库,但现在您应该了解如何正确操作。

【讨论】:

  • 完美。我曾尝试过与此类似的尝试,但我尝试执行 CNT = () 而不是:CNT。非常感谢!
猜你喜欢
  • 2020-02-28
  • 1970-01-01
  • 1970-01-01
  • 2015-04-06
  • 2011-07-28
  • 2010-11-26
  • 1970-01-01
  • 2013-10-12
  • 2020-08-18
相关资源
最近更新 更多