Firebird触发器SQL验证查询

时间:2016-03-09 19:16:54

标签: sql triggers firebird ddl

相对简单的问题。我正在尝试执行语句并在调整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,col:5

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

2 个答案:

答案 0 :(得分: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 ; ^

我无法检查它是否有效,因为我没有你的数据库,但现在你应该看看如何做到这一点。

答案 1 :(得分:2)

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