火鸟程序错误

Error in Firebird Procedure

我必须执行一次查询才能获得一个参数(我需要一个“1”),但是这个参数可以在不同的单元格中,例如:

+--------------+--------------+--------------+
|....cell1.....|.....cell2....|....cell3.....|
+--------------+--------------+--------------+
|....here......|.....here.....|....or here...|
+--------------+--------------+--------------+

我必须捕获,然后,如果它等于一个,则执行其他查询以获得我想要的。我尝试用这段代码做一个过程:

SET TERM !! ;

CREATE PROCEDURE GET_CASH(
    TICKET VARCHAR(15))
RETURNS ( TOTAL integer
)
AS
BEGIN
    FOR SELECT a.ID_FPAY1, a.FPAY1_IMPORT, a.ID_FPAY2, a.FPAY2_IMPORT, a.ID_FPAY3, a.FPAY3_IMPORT
    FROM TB_TICKETS_HIS a WHERE a.ID_TICKET = TICKET 
    DO
    BEGIN
        IF a.ID_FPAY1 = 1 THEN TOTAL = a.FPAY1_IMPORT;
        IF a.ID_FPAY2 = 1 THEN TOTAL = a.FPAY2_IMPORT;
        IF a.ID_FPAY3 = 1 THEN TOTAL = a.FPAY3_IMPORT;
        SUSPEND;
    END
END!!

SET TERM ; !!

执行查询时出现此错误:

SQL Message : -104
Invalid token

Engine Code    : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 11, column 5
DO

我尝试删除 FOR 和 Do,但出现此错误:

SQL Message : -104
Invalid token

Engine Code    : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 11, column 5
BEGIN

有人可以帮助我完成此过程或向我解释失败的原因吗?

如果要在 Firebird 存储过程中使用 FOR SELECT .. DO(或单例 select),则需要使用 INTO 来填充参数值。

另请参阅 FOR SELECT 上的 Firebird 参考资料:

  • requires an INTO clause that is located at the end of the SELECT ... FROM ... specification. In each iteration of the loop, the field values in the current row are copied to the list of variables specified in the INTO clause. [..]

也就是说,根据这个存储过程的用途,你需要声明额外的return变量或局部变量来保存select的相关字段,例如:

CREATE PROCEDURE GET_CASH(
    TICKET VARCHAR(15))
RETURNS ( TOTAL integer
)
AS
declare id_fpay1 integer;
declare fpay1_import integer;
declare id_fpay2 integer;
declare fpay2_import integer;
declare id_fpay3 integer;
declare fpay3_import_integer
BEGIN
    FOR SELECT a.ID_FPAY1, a.FPAY1_IMPORT, a.ID_FPAY2, a.FPAY2_IMPORT, a.ID_FPAY3, a.FPAY3_IMPORT
        FROM TB_TICKETS_HIS a WHERE a.ID_TICKET = TICKET 
        into id_fpay1, fpay1_import, id_fpay2, fpay2_import, id_fpay3, fpay3_import
    DO
    BEGIN
        IF a.ID_FPAY1 = 1 THEN TOTAL = a.FPAY1_IMPORT;
        IF a.ID_FPAY2 = 1 THEN TOTAL = a.FPAY2_IMPORT;
        IF a.ID_FPAY3 = 1 THEN TOTAL = a.FPAY3_IMPORT;
        SUSPEND;
    END
END

但是,您可以通过在 select 语句中执行该逻辑来大大简化此操作:

CREATE PROCEDURE GET_CASH(
    TICKET VARCHAR(15))
RETURNS ( TOTAL integer
)
AS
BEGIN
    FOR SELECT case 
            when a.id_pay3 = 1 then a.fpay3_import
            when a.id_pay2 = 1 then a.fpay2_import
            when a.id_pay1 = 1 then a.fpay1_import
        end as total
        FROM TB_TICKETS_HIS a WHERE a.ID_TICKET = TICKET 
        into total
    DO
    BEGIN
        SUSPEND;
    END
END

相反的顺序只是为了保留与原始代码段中相同的逻辑。从技术上讲,为了保留该逻辑,需要额外的处理来保留 total 的先前值,就像您编写的代码所做的那样,但我认为这是您代码中的错误。