【问题标题】:PL/SQL function compilation errorsPL/SQL 函数编译错误
【发布时间】:2013-05-31 18:43:47
【问题描述】:

我正在尝试编写一个 PL/SQL 函数,该函数将球员姓名作为参数并返回在他最喜欢的体育场进行的比赛数。

如果玩家表中不存在玩家,该函数应返回 -2。如果玩家存在但他没有最喜欢的体育场,则该函数返回 -1。

这就是我所拥有的:

create or replace function favS(pname varchar2) return number
as
    fav_stadium_count number;
begin
    select count(case when favstadiums.stadium = matches.stadium then 1 else null end) into fav_stadium_count
    from favstadiums
    right join players
    on favstadiums.player = players.name
    outer join matches
    on favstadiums.stadium = matches.stadium;
    if (count(case when favstadiums.stadium = matches.stadium then 1 else null end) > 0) then
        return fav_stadium_count;
    end if;
    if players.name is null then
        return -2;
    end if;
    if (count(case when favstadiums.stadium = matches.stadium then 1 else null end) < 1) then
        return -1;
    end if;
end;

但我得到以下编译错误:

Line 9: ORA-00933: SQL command not properly ended
Line 5: SQL Statement ignored

关于如何解决这个问题的任何想法?

如果有帮助,这里是数据库的关系图:

编辑(针对 Ted):

create or replace function favS(pname varchar2) return number
as
    fav_stadium_count number;
    vplayername varchar(100);
begin
    select count(case when favstadiums.stadium = matches.stadium then 1 else null end) into fav_stadium_count,
    players.name into vplayername
    from favstadiums
    right join players
    on favstadiums.player = players.name
    left outer join matches
    on favstadiums.stadium = matches.stadium
    where name = pname;
    if (fav_stadium_count > 0) then
        return fav_stadium_count;
    end if;
    if vplayername is null then
        return -2;
    end if;
    if (fav_stadium_count < 1) then
        return -1;
    end if;
end;

【问题讨论】:

  • 我不确定这个 ERD 是否比语句更容易阅读。
  • 您编辑的查询的语法错误。你需要SELECT value1, value2 INTO variable1, variable2 FROM ...

标签: sql oracle plsql


【解决方案1】:
if (count(case when favstadiums.stadium = matches.stadium then 1 else null end) > 0) then
   return fav_stadium_count;
end if;

应该是:

if (fav_stadium_count > 0) then
   return fav_stadium_count;
end if;

就以下声明而言:

if players.name is null then
   return -2;
end if;

也是错的。那里也没有选择语句。您应该使用某种变量,例如 fav_stadium_count 来存储您想要的名称。

if (count(case when favstadiums.stadium = matches.stadium then 1 else null end) < 1) then
    return -1;
end if;

应该变成:

if (fav_stadium_count < 1) then
    return -1;
end if;

【讨论】:

  • 为什么我不能使用 count() 而不是 sum()?
  • 哇,我在想什么!!!伙计,如果(计数(...))?你到底在数什么?那里没有 select 语句,它只是一个 if 语句... :)
  • 谢谢。您在上面解释if players.name is null then... 错误的部分。你能给我看一个带代码的例子吗?我无法理解我将如何做到这一点。
  • 如果 players.name 您试图引用 table.column,则无法通过 if 语句完成。 players.name 只能针对表 players 上的语句进行评估,例如 select players.name from players where name='Ted'
  • 所以你需要像select players.name into vplayername from players where name='Ted' 这样的东西,然后你可以做像if vplayername is null then return -2; end if; 这样的if 语句。不要忘记在 begin 声明之前声明 vplayername
【解决方案2】:

我认为是您的联接语法不正确。尝试:INNER JOIN 和 LEFT OUTER JOIN。执行和外部连接,但未指定哪一方出错。

【讨论】:

  • 连接非常好。 outer joinfull outer join,不需要“边”。
  • 使用您的建议,它确实消除了上面原来的 2 个错误。我现在只有if players.name is null then 行有错误。我收到错误:PLS-00357: Table,View Or Sequence reference 'PLAYERS.NAME' not allowed in this context。有任何想法吗?谢谢
  • 在您的图表中,表名称是 PLAYER 而不是 PLAYERS。其他问题是您没有在查询中使用输入变量 pname,因此您正在使用完全外连接查询所有玩家。另外,我认为您的 if 条件不会起作用,我认为您的查询中需要该逻辑(请参阅 Ted 的回答)。
【解决方案3】:

作为一般设计建议,我会说这个架构缺少正确的主键 - 每个表都应该有一个数字 id 列,因为依赖名称等真实值的唯一性或不变性是不明智的。

然后功能应该被打破,因为这段代码在一个地方做了太多。查找玩家名称的 id 可能应该在不同的函数中,如果没有找到玩家,它可以返回 null,或者可能引发错误(就像将 null 玩家名称传递给函数一样)。

我会将“查找播放器”功能分解为另一个函数,如果播放器名称不存在,则返回 null 而不是播放器 ID。

返回最喜欢的体育场的数量应该是返回一个整数,0 或更大,不需要幻数来指示其他条件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多