在Firebird中,如何在过程中编写多个if语句?

时间:2018-04-22 02:57:06

标签: sql firebird

我在Firebird中编写了一个sql脚本来进行分配。首先,我必须创建一个2列表并添加一些值(这些值不应该做任何事情)

--Create the table
create table salary_class (
class varchar(5),
occurrence int ) ;

commit work;

--Add Values to our table
insert into salary_class (class, occurrence)
values ('ELITE', 0);
insert into salary_class (class, occurrence)
values ('HIGH', 0);
insert into salary_class (class, occurrence)
values ('MID', 0);
insert into salary_class (class, occurrence)
values ('LOW', 0);

commit work;

在提交工作之后,我创建了一个程序。它应该根据传递给它的数字返回某个字符串。

--Create f_class procedure
set term # ;
create procedure f_class(salary SALARY)

returns (lv VARCHAR(10)) as
begin
    --If statements for each occurrence level
    if (salary <= 39999) then
    lv = 'LOW';
    suspend;

    if (salary <= 67999) then
    lv = 'MID';
    suspend;

    if (salary <= 99999) then
    lv = 'HIGH';
    suspend;

    if (salary >= 100000) then
    lv = 'ELITE';
    suspend;

end#

set term ; #

--Demonstrate that f_class function works correctly
  select lv from f_class(20000);
  select lv from f_class(67999);
  select lv from f_class(68000);
  select lv from f_class(120000);

调用该函数给我

LV
null
null
null
ELITE

但它应该给我

LV
LOW
MID
HIGH
ELITE

如果有人能够对此有所启发,我们将不胜感激。在过去的两天里,我一直把头发拉过Firebird手册。

1 个答案:

答案 0 :(得分:2)

您的代码中存在多个问题。第一个问题是您无条件地使用suspend,这意味着每次调用存储过程都会返回4行,这取决于条件可能包含null值或先前的值。

这似乎不是您所期望的,因为您的问题的预期输出似乎与每个单独薪水的期望相匹配,而实际输出是最后一个语句的输出(select lv from f_class(120000);)。

第二个问题是您使用单独的if语句,这会导致评估多个条件(例如,值1将返回lowmidhigh(2x ),值67999将返回nullmidhigh(2x)等。

为了解决您的问题,有一些解决方案:

  1. 使用链式if .. then .. else

    if (salary <= 39999) then
        lv = 'LOW';
    else if (salary <= 67999) then
        lv = 'MID';
    else if (salary <= 99999) then
        lv = 'HIGH';
    else if (salary >= 100000) then
        lv = 'ELITE';
    
    suspend;
    

    suspend也会阻止输出多行。

  2. if - 语句替换为搜索到的case

    lv = case 
            when salary <= 39999 then 'LOW'
            when salary <= 67999 then 'MID'
            when salary <= 99999 then 'HIGH'
            when salary >= 100000 then 'ELITE'
         end;
    
    suspend;
    

    您还可以将最后when salary >= 100000 then 'ELITE'替换为else 'ELITE'

  3. 但是,您在问题中将其描述为函数让我觉得这可能是完全错误的解决方案。存储过程不是函数,它们是可选地返回值的过程,或者 - suspend - 生成动态“表”(结果集)。如果您需要真正的功能,并且您正在使用Firebird 3,请使用stored functions

    create function f_class(salary SALARY) returns varchar(10)
    as
    begin
        return case 
            when salary <= 39999 then 'LOW'
            when salary <= 67999 then 'MID'
            when salary <= 99999 then 'HIGH'
            when salary >= 100000 then 'ELITE'
        end;
    end
    

    然后您可以像

    一样使用它
    select f_class(120000) from rdb$database;
    

    rdb$database的使用纯粹是为了说明,可以在任何可以使用普通SQL函数的地方使用存储函数。