【问题标题】:getting Warning: Function created with compilation errors收到警告:创建的函数存在编译错误
【发布时间】:2019-11-08 04:43:15
【问题描述】:

我在执行以下函数时遇到错误。我已经有一段时间了。我是 oracle 的新手,所以我无法更正它。有人可以帮忙吗?

create or replace function rever(x int)
return number
is
y varchar2(30);
c varchar2(30);
v int;
begin
y:=to_char(x);
c:=reverse(y);
v:=to_number(c);
return v;
end rever;
/

以下显示为错误消息

LINE/COL ERROR
-------- ----------------------------------------------------------------- 
9/1      PL/SQL: Statement ignored 
9/4      PLS-00201: identifier 'REVERSE' must be declared

【问题讨论】:

  • 运行show errors查看错误信息

标签: plsql oracle10g


【解决方案1】:

Oracle 没有在 plsql 中提供函数来进行字符串反转。

     create or replace function rever(x int)
     return number
     is
       y varchar2(30);
       c varchar2(30);
       v int;
     begin
       y:=to_char(x);

       -- Loop other each char in a string from the last to the first element  
       for i in reverse 1.. length(y)
       loop 
         c:= c|| substr(y,i,1); 
       end loop; 
       v:=to_number(c);
       return v;
     end rever;
     /

测试:

     begin
       dbms_output.put_line(rever(1));
       dbms_output.put_line(rever(12));
       dbms_output.put_line(rever(21));
       dbms_output.put_line(rever(123));
     end;
     /

结果:

dbms_output
    1
    21
    12
    321

db小提琴here

【讨论】:

  • “Oracle 没有在 plsql 中提供函数来进行字符串反转。” 但是我们可以在 PL/SQL 中使用 SQL 函数。见my answer。
  • select reverse(c) into x from dual 下面的语句正在执行。为什么?你能解释一下..
  • 因为reverse是SQL引擎中的一个函数
【解决方案2】:

Oracle 中没有 PL/SQL reverse() 函数。所以这不起作用:

declare
  v varchar2(20);
begin
  v:= reverse('krow not does ti');
  dbms_output.put_line(v);
end;  
/

它会抛出你得到的 PLS-00201 错误。

但是,我们可以在 PL/SQL 中使用 未记录的 SQL 函数,但只能通过调用 SQL 引擎:

declare
  v varchar2(20);
begin
  select reverse('skrow ti') into v from dual;
  dbms_output.put_line(v);
end;  
/

当然,因为reverse() 没有记录,我们不应该使用它,至少在生产代码中是这样。不知道为什么它没有记录。我认为 Oracle 将它用于反向索引,所以可能对可逆字符串大小有一些限制。

这是一个db<>fiddle 演示。


性能有点差

我认为这是从 PL/SQL 引擎迁移到 SQL 引擎并再次返回的成本。所以归结为用例。如果我们正在编写一个仅用于纯 PL/SQL 的函数,那么我认为您的方法是更好的方法。但是,如果我们正在编写一个要在 SQL 中使用的函数,那么我会考虑使用 Oracle 内置函数,即使它不受支持。

虽然老实说,我不记得上次在现实生活中使用 reverse() 函数(Oracle 的或手动的)是什么时候(而不是在论坛中回答问题或类似的 Code Golf 问题 :))。

【讨论】:

  • 感谢您的提示。我还不知道这个功能。性能有点差,即使值更小。 db小提琴here
【解决方案3】:

仅供娱乐,不使用PL/SQL,使用一点正则表达式进行分层查询:

SQL> with test (col) as
  2    (select 'Littlefoot' from dual)
  3  select listagg(one, '') within group (order by lvl desc) reversed
  4  from (select level lvl, regexp_substr(col, '.', 1, level) one
  5        from test
  6        connect by level <= length(col)
  7       );

REVERSED
--------------------------------------------------------------------------
toofelttiL

SQL>

或者,重写为函数:

SQL> create or replace function f_reverse (par_col in varchar2)
  2    return varchar2
  3  is
  4    retval varchar2(1000);
  5  begin
  6    select listagg(one, '') within group (order by lvl desc)
  7      into retval
  8      from (select level lvl, regexp_substr(par_col, '.', 1, level) one
  9            from dual
 10            connect by level <= length(par_col)
 11           );
 12    return retval;
 13  end;
 14  /

Function created.

SQL> select empno, f_reverse(empno) rev_empno,
  2         ename, f_reverse(ename) rev_ename
  3  from emp
  4  where rownum <= 3;

     EMPNO REV_EMPNO  ENAME      REV_ENAME
---------- ---------- ---------- ----------
      7369 9637       SMITH      HTIMS
      7499 9947       ALLEN      NELLA
      7521 1257       WARD       DRAW

SQL>

【讨论】:

    猜你喜欢
    • 2013-06-13
    • 2018-10-26
    • 2014-03-16
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多