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 不需要查询所有行,只需检查是否有一个或多个。
比较简单的问题。我试图在调整 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 不需要查询所有行,只需检查是否有一个或多个。