【问题标题】:Trying to use a where statement in cursor creation (PL/SQL)尝试在游标创建中使用 where 语句 (PL/SQL)
【发布时间】:2019-07-16 03:28:23
【问题描述】:

我正在尝试创建一个块,该块接受来自提示的输入并使用该输入来过滤光标的结果集。请记住,我是这里的新手,所以我可能会犯一个非常常见的错误,感谢您的帮助。我当前的代码如下。

Set serveroutput on

DECLARE
  ACCEPT a PROMPT  “Please Enter a Date,  eg. Format -  01 or 30"

  datev char
  datev := &a;

  CURSOR cur_day_cursor IS
    SELECT Arrival_Date Adate
      FROM FLIGHT
      WHERE TO_CHAR(Arrival_Date, ‘DD’) = datev;

  cur_day_cursor_var cur_day_cursor%ROWTYPE;
BEGIN
  OPEN Cur_day_cursor;

  LOOP
    Fetch Cur_day_cursor
      INTO cur_day_cursor_var;
    EXIT WHEN cur_day_cursor%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE (cur_day_cursor_var.Adate);
  END LOOP;

  IF cur_day_cursor%ISOPEN THEN
    CLOSE cur_day_cursor;
  END IF;
END;

where 语句导致了我的错误,所以我想我可能必须让光标收集所有数据,然后在显示时对其进行过滤,但我不确定我是否可以这样做。

我在第 9 行不断收到 ERROR 的错误:- ORA-06550:第 9 行,第 1 列: PLS-00103:在预期以下情况之一时遇到符号“WHERE”: 开始函数杂注过程子类型类型 当前光标删除 之前存在

【问题讨论】:

    标签: sql oracle plsql oracle11g


    【解决方案1】:

    我不知道为什么 Oracle 在WHERE 报告错误。有时解析器会被糟糕的语法弄糊涂,并没有指出真正的问题。您在游标定义之前有几个语法错误。

    ACCEPT 是 SQLPlus 命令,而不是 PL/SQL 语句。将ACCEPT 行移到DECLARE 上方。

    另外,您的变量声明和初始化不正确。赋值应该是声明行的一部分;您需要为 CHAR 数据类型提供长度;并且替换值应该放在引号中以被视为字符串。您的行的有效版本是:

    datev  char(2) := '&a';
    

    【讨论】:

    • 对不起,“接受提示”请输入日期,例如格式 - 01 或 30”部分代码,放在我初始代码中的声明部分之前。我只是在搞乱某些事情,试图让代码运行。我已经尝试了建议的解决方案,但我遇到了一个问题,即在输入提示的变量 (datev) 屏幕截图后脚本立即挂起 - i.imgur.com/kFCsV5Z.jpg
    • 您发布的代码在 PL/SQL 块后面没有斜线,这是实际执行它所必需的。所以可能只是 SQLPlus 正在等待更多输入。在最后的END; 后面单独添加一个/。另一种可能性只是驱动循环的查询需要很长时间才能执行,但我认为在这种情况下这是值得怀疑的。
    【解决方案2】:

    我运行了与上面相同的查询,结果非常好。 您的语法和逻辑错误很少,我在您的查询中更正了这些错误。语法错误是 -

    datev char
    datev := &a;
    

    您不能在 PL/SQL 中进行这样的初始化。您可能必须像下面这样在一行中完成它 -

    datev char := &a;
    

    逻辑错误是 -

    1. 既然知道返回的值是 NUMBER,为什么还要使用 CHAR 变量来存储数据。
    2. 您希望数字为 1-31;那你为什么选择char的默认大小为1。如果你提供2位数字,它将失败
    3. 即使将 CHAR 的大小增加到 CHAR(2),当用户输入像 1 或 01 这样的数字时,您也不会得到结果,因为对于字符比较,'1' != '1'(标记最后有多余的空间,因为 char(2));还有'1'!='01'。 上面的唯一解决方案是使用 NUMBER 数据类型。

    现在我在这里发布与您的查询类似的查询,但更改了列名和表名。请替换为您所需的名称并尝试 - (注意不要使用 PL/SQL 块执行 ACCEPT....)。应该先在 SQL 提示符下完成,然后再运行另一个 DECLARE 部分。

    --ACCEPT a NUMBER PROMPT  'Please Enter a Date,  eg. Format -  01 or 30 :'
    --Run the above line first in SQL Prompt and then execute the rest as whole
    DECLARE
      datev NUMBER(2) := &a;
      CURSOR cur_day_cursor IS
        SELECT Ename, HireDate Adate
          FROM Emp
          WHERE TO_CHAR(HireDate, 'D') = datev;
      cur_day_cursor_var cur_day_cursor%ROWTYPE;
    BEGIN
      OPEN Cur_day_cursor;
      LOOP
        Fetch Cur_day_cursor
          INTO cur_day_cursor_var;
        EXIT WHEN cur_day_cursor%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE (cur_day_cursor_var.Adate);
      END LOOP;
      IF cur_day_cursor%ISOPEN THEN
        CLOSE cur_day_cursor;
      END IF;
    END;
    /
    

    【讨论】:

      【解决方案3】:

      问题似乎在于‘DD’ 周围的单引号不是单引号。看起来代码是在编辑器中创建的,它将撇号更改为那些特殊的“看起来有点像单引号但不是真的”字符。将原始版本的 WHERE 子句替换为以下内容:

      WHERE TO_CHAR(Arrival_Date, 'DD') = datev;
      

      我怀疑你会没事的。

      给自己一个好的代码编辑器。 :-)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-06
        • 2020-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-14
        相关资源
        最近更新 更多