PL / SQL:创建函数:无效的标识符

问题描述

我有一个通过Oracle github(https://github.com/oracle/docker-images/tree/master/OracleDatabase/SingleInstance)上的docker镜像构建的oracle 19c ee数据库。我正在尝试按照他们的示例来介绍如何创建函数from here

我完全复制了他们的示例。设置表和数据:

CREATE TABLE orders (
    customer_id number(10),order_total NUMBER(11,2)
);
INSERT INTO orders (customer_id,order_total) VALUES (1,200.01)

实际功能:


CREATE FUNCTION get_bal(acc_no IN NUMBER) 
   RETURN NUMBER 
   IS acc_bal NUMBER(11,2);
   BEGIN 
      SELECT order_total 
      INTO acc_bal 
      FROM orders 
      WHERE customer_id = acc_no; 
      RETURN(acc_bal); 
    END;

但是,当我尝试创建函数时,我一直遇到此错误

Query 2 ERROR: ORA-06550: line 5,column 27:
PL/SQL: ORA-00904: "ACC_NO": invalid identifier
ORA-06550: line 2,column 7:
PL/SQL: SQL Statement ignored
ORA-06550: line 6,column 7:
PLS-00372: In a procedure,RETURN statement cannot contain an expression
ORA-06550: line 6,column 7:
PL/SQL: Statement ignored

我在做什么错了?

解决方法

这个例子对我有用。您一定输入了错误的内容。您确定您的功能与手册中的功能完全相同吗?

ORA-00904:“ ACC_NO”:无效的标识符

建议声明acc_bal NUMBER(11,2);丢失或不同。

PLS-00372:在过程中,RETURN语句不能包含表达式

表示您的代码是一个过程,而不是一个函数。

SQL> CREATE TABLE orders (
  2      customer_id number(10),3      order_total NUMBER(11,2)
  4  );

Table created


SQL> INSERT INTO orders (customer_id,order_total) VALUES (1,200.01);

1 row inserted


SQL> CREATE FUNCTION get_bal(acc_no IN NUMBER)
  2     RETURN NUMBER
  3     IS acc_bal NUMBER(11,2);
  4     BEGIN
  5        SELECT order_total
  6        INTO acc_bal
  7        FROM orders
  8        WHERE customer_id = acc_no;
  9        RETURN(acc_bal);
 10      END;
 11  /

Function created


SQL> select get_bal(1) from dual;

GET_BAL(1)
----------
    200.01

顺便说一句,虽然我通常是Oracle文档的忠实拥护者,并且该示例确实说明了如何创建PL / SQL函数,但我认为它可以改进:

  • 出于可读性考虑,最好为每个声明分配自己的行,因此最好将行3分成两行,并在行上acc_bal NUMBER(11,2);
  • ISAS关键字在此处可以互换,但是肯定create ... as(类似于您用来创建表或视图的内容)的读取效果比create ... is好。
  • 可以理解,作者并不想在解释之前通过引入%type来使示例复杂化,但是更高级的版本将使用acc_bal orders.order_total%type;来使acc_bal继承其数据类型。从表列而不是对其进行硬编码。这适用于该函数中使用的所有三个值。
  • 参数和变量的名称还可以-至少是明确的-但是,对于与表列相同的参数和变量使用命名方式时,存在危险。有一天,您将输入WHERE c.customer_id = customer_id,并想知道为什么返回的行比预期的多。同样,作者不想在第一个示例中进入整个讨论也是可以理解的,但这是需要考虑的事情。您可以在函数内使用get_bal.acc_no,或将camelCase用作参数和变量,或将p_前缀作为'parameter'等。
  • 布局的基本规则是,诸如if/elsebegin/end之类的开始和结束关键字应左对齐。第10行的END在其开口BEGIN下未对齐。我认为在第一行之后缩进整个内容是一种有效的个人布局选择,但对我而言,它不会添加任何内容。
  • 一个好主意是在每个SQL语句的周围留空行,以避免出现坚固的文本墙。就个人而言,我希望第9行的RETURN前留空行。
  • RETURN子句不需要任何括号。编译器将忽略第9行的多余括号。我会丢失它们。
  • 这是一个好习惯(尽管是可选的),在结尾END中包含过程/函数名称,因此第10行将变为END get_bal;
  • COBOL风格的大写习惯在行业中很普遍,但没有必要。 (PL / SQL的语法著名地基于Ada,尽管有些语法也指向ALGOL和PL / 1-从来没有大写过。)我将通过简化整个内容来提高可读性。

有了这些更改,我得到了:

create or replace function get_bal
    ( inAccNo in orders.customer_id%type )
    return orders.order_total%type
as
    accBal orders.order_total%type;
begin
    select order_total into accBal
    from   orders
    where  customer_id = inAccNo;

    return accBal;
end;

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...