Firebird 触发器 SQL 验证查询

Firebird Trigger SQL Validate Query

比较简单的问题。我试图在调整 firebird 触发器上的 INSERT 值之前执行语句并检查值。我见过许多示例,其中评估了新值,然后执行了后续语句,但 none 是我想要的。更容易显示...

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 ; ^

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

通常 IF (new.ID = 0) then execute statement 'blah';会工作,但是当我写这个触发器时,它在语法上被接受但是当值改变时我收到以下错误消息:

arithmetic exception, numeric overflow, or string truncation string right truncation At trigger 'STOP_PREMIX_INSERT_PRODUCECEDD' line: 6, col: 5

我可能漏掉了一个分号,或者这可能是不可能的,无论如何,我们将不胜感激。

应该是这样的:

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 ; ^

我无法检查它是否会工作,因为我没有你的数据库,但现在你应该知道如何正确地做到这一点。

它不起作用的原因是你正在构造一个字符串,然后将它与一个整数进行比较。结果转换失败。事实上,字符串包含看起来像 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 不需要查询所有行,只需检查是否有一个或多个。