首页 > 解决方案 > Firebird 程序中的错误

问题描述

我必须做一个查询才能得到一个参数(我需要一个“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

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

标签: sqlstored-proceduresfirebird-3.0firebird-psql

解决方案


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

另请参阅 Firebird 参考FOR SELECT

  • 需要一个INTO位于规范末尾的子句SELECT ... FROM ...。在循环的每次迭代中,当前行中的字段值都被复制到INTO子句中指定的变量列表中。[..]

换句话说,根据这个存储过程的目的,你需要声明额外的返回变量或局部变量来保存 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就像您编写的代码所做的那样,但我认为这是您代码中的一个错误。


推荐阅读