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

Plsql PL/SQL:创建函数:标识符无效,plsql,Plsql,我通过Oracles github()上的docker映像构建了一个oracle 19c ee数据库。我试图按照他们的例子来创建函数 我完全照搬了他们的例子。设置表和数据: CREATE TABLE orders ( customer_id number(10), order_total NUMBER(11,2) ); INSERT INTO orders (customer_id, order_total) VALUES (1, 200.01) 实际功能: CREATE F

我通过Oracles github()上的docker映像构建了一个oracle 19c ee数据库。我试图按照他们的例子来创建函数

我完全照搬了他们的例子。设置表和数据:

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\u bal编号(11,2)缺失或不同

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

指示代码是过程,而不是函数

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)分成两行在它自己的行上
  • ,因为
    关键字在这里是可互换的,但肯定是
    创建。。。因为
    (类似于您可能用来创建表或视图的内容)比
    创建更容易阅读。。。是
  • 可以理解,作者不想在解释之前引入
    %type
    使示例复杂化,但更高级的版本将使用
    acc\u bal orders.order\u total%type
    使
    acc_bal
    从表列继承其数据类型,而不是硬编码。这适用于函数中使用的所有三个值
  • 参数和变量的名称是可以的-它们至少是清晰的-但是当使用与表列相同的参数和变量命名模式时,会有危险。总有一天,你会输入
    其中c.customer\u id=customer\u id
    ,并想知道为什么你得到的行数比预期的多。同样可以理解的是,作者不想在第一个例子中涉及到整个讨论,但这是值得思考的。您可以在函数中使用
    get\u bal.acc\u no
    ,或者对参数和变量使用camelCase,或者对“参数”等使用
    p\u
    前缀
  • 布局的基本规则是打开和关闭关键字,如
    if/else
    begin/end
    ,应该左对齐。第10行的
    END
    在其开口
    BEGIN
    下未对齐。我想在第一行之后缩进整个内容是一个有效的个人布局选择,但对我来说,它没有添加任何内容
  • 最好在每个SQL语句周围留下空行,以避免形成一堵坚实的文本墙。就我个人而言,我希望在第9行的
    返回之前有一个空行
  • RETURN
    子句不需要任何括号。编译器忽略第9行的多余括号。我会失去他们的
  • 好的做法是(尽管是可选的)将过程/函数名称包含在结束
    中,因此第10行将成为
    结束get\u 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;

有趣!那太有帮助了。我试图使用
TablePlus
创建函数,所以我怀疑它单独运行了每条语句?当我在
sqlplus
中运行它时,它会工作。谢谢在什么情况下,
作为
关键字是不可互换的?文档中没有涉及到这一点,它们在创建PL/SQL对象(过程、函数、包、类型)时是可以互换的,这可能就是为什么PL/SQL手册没有对此进行讨论的原因。在创建表和视图或SQL查询中的列别名时,它们是不可互换的。