【问题标题】:Getting PLS-00103 Error. PLS-00103: Encountered the symbol "RETURN"出现 PLS-00103 错误。 PLS-00103:遇到符号“返回”
【发布时间】:2021-05-06 08:30:14
【问题描述】:

我是 PL/sql 的新手,我目前正在编写一些 PL/SQL 代码,这些代码必须从两个表中提取数据。到目前为止,我的代码不断收到错误 PLS-00103:在期待其中之一时遇到符号“RETURN” 以下: * & = - + ;

at in 是 mod 余数不是 rem

这是我目前的代码

CREATE OR REPLACE FUNCTION LISTNATION(N_NAME in VARCHAR2, R_NAME IN VARCHAR2, R_REGIONKEY IN NUMBER)
  2  RETURN VARCHAR2 IS
  3  R_REGIONKEY NUMBER(3);
  4  R_NAME VARCHAR2(50);
  5  N_NAME VARCHAR2(50);
  6  
  7  BEGIN
  8  select r_regionkey, r_name, n_name
  9  from region
 10  inner join nation
 11  on r_regionkey = n_regionkey;
 12  
 13  dbms_output.put_line = (R_REGIONKEY || ' ' || R_NAME || ':' || N_NAME || ',')
 14  
 15  END;
 16  /

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    您遇到错误的直接原因(在问题的原始版本中)是您在第 4 行末尾缺少分号。

    但还有不少其他问题:

    • 您在字符串文字周围使用双引号 " 而不是单引号 '。这些是用于标识符,而不是字符串。
    • 您的局部变量与参数相同,但您不需要所有这些参数。
    • 你没有选择进入任何东西;并且您的查询将返回多行。
    • 您的查询没有where 子句,因此它将查找所有地区的数据。
    • 你打错了dbms_output 电话;它缺少右括号(同样,在原始问题中)并且不应该有 =
    • 您将返回 test,但尚未声明。

    因此,要让函数使用 dbms_output 来显示结果 - 这依赖于处理该输出的调用者,您不应该假设 - 您可以这样做:

    CREATE OR REPLACE FUNCTION LISTNATION(P_R_REGIONKEY IN NUMBER)
    RETURN VARCHAR2 IS
      L_R_NAME REGION.R_NAME%TYPE;
      L_N_NAME NATION.N_NAME%TYPE;
    
    BEGIN
      FOR l_row IN (
        select r.r_name, n.n_name
        from region r
        inner join nation n
        on r.r_regionkey = n.n_regionkey
        where r.r_regionkey = p_r_regionkey
      ) LOOP
    
        dbms_output.put_line (P_R_REGIONKEY || ' ' || l_row.R_NAME || ':' || l_row.N_NAME);
    
      END LOOP;
    
      RETURN 'test';
    END;
    /
    

    这会为您的查询添加一个过滤器,将其转换为隐式游标,然后循环遍历结果。

    db<>fiddle 包含一些虚构的数据,表名和列名取自您的尝试。

    不清楚你真正想要返回什么;您可能需要一个以逗号分隔的国家名称列表,在这种情况下请查看the listagg() function。例如,您可以执行以下操作:

    CREATE OR REPLACE FUNCTION LISTNATION(P_R_REGIONKEY IN NUMBER)
    RETURN VARCHAR2 IS
      L_RESULT VARCHAR2(4000);
    
    BEGIN
      select listagg(n.n_name, ',') within group (order by n.n_name)
      into l_result
      from region r
      inner join nation n
      on r.r_regionkey = n.n_regionkey
      where r.r_regionkey = p_r_regionkey;
    
      RETURN l_result;
    END;
    /
    

    然后您可以调用它来获取单个值列表。

    db<>fiddle

    虽然在查询周围使用 PL/SQL 函数包装器似乎不是很有用。想必这是一个练习……


    有没有办法显示它,以便在列出所有国家时只显示地区键和地区一次?

    您可以更改第二个函数以包含区域信息,并将其与 listagg 结果连接:

    CREATE OR REPLACE FUNCTION LISTNATION(P_R_REGIONKEY IN NUMBER)
    RETURN VARCHAR2 IS
      L_RESULT VARCHAR2(4000);
    
    BEGIN
      select r.r_regionkey || ' ' || r.r_name || ': '
        || listagg(n.n_name, ',') within group (order by n.n_name)
      into l_result
      from region r
      inner join nation n
      on r.r_regionkey = n.n_regionkey
      where r.r_regionkey = p_r_regionkey
      group by r.r_regionkey, r.r_name;
    
      RETURN l_result;
    END;
    /
    

    然后为您感兴趣的每个区域键调用它。

    db<>fiddle

    您的措辞方式听起来像是您不想传递区域键,而是想一次查看所有区域;又想用dbms_output,不理想;并且真的不想返回任何东西。因此,您可以改用一个过程,更改游标查询以恢复区域名称,然后在循环内的 put_line 调用中连接:

    CREATE OR REPLACE PROCEDURE LISTNATION IS
    BEGIN
      FOR l_row IN (
        select r.r_regionkey, r.r_name,
          listagg(n.n_name, ',') within group (order by n.n_name) as names
        from region r
        inner join nation n
        on r.r_regionkey = n.n_regionkey
        group by r.r_regionkey, r.r_name
        order by r.r_regionkey
      ) LOOP
    
        dbms_output.put_line (l_row.R_REGIONKEY || ' ' || l_row.R_NAME || ': ' || l_row.names);
    
      END LOOP;
    END;
    /
    
    dbms_output:
    1 EMEA: FRANCE,UNITED KINGDOM
    2 APAC: CHINA
    

    db<>fiddle

    当然有很多变化,这完全取决于你想要发生什么,但你应该能够适应其中一种方法。另一个是让一个函数或过程生成一个引用游标,但同样不清楚你想要什么。但是使用dbms_output 并不是一个好主意,因为调用者可能没有使用查找并显示它的客户端。

    【讨论】:

    • 无论如何都可以显示它,以便在列出所有国家时只显示区域键和区域一次? dbms_output:1 EMEA:法国、英国 2 APAC:中国
    • @newtoprogramming - 有多种方法,具体取决于您实际尝试执行的操作。我已经添加了这两种方法的修改版本,但还有其他的。
    猜你喜欢
    • 2018-06-06
    • 2018-01-23
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多