【问题标题】:PL/SQL: SQL Statement ignoredPL/SQL:忽略 SQL 语句
【发布时间】:2018-04-14 17:40:43
【问题描述】:

我是 PL/SQL 的新手,正在尝试创建一个存储过程,该过程将使用以下代码填充表:

DROP TABLE Times CASCADE CONSTRAINTS;

CREATE TABLE Times (
    sale_day DATE NOT NULL,
    day_type VARCHAR2(50) NOT NULL, 
    PRIMARY KEY (sale_day));


CREATE OR REPLACE PROCEDURE Time_Procedure
AS
    l_sale_date date;
    temp_value varchar2(5);
CURSOR c1 IS SELECT SALE_DATE FROM SALES;

BEGIN
    OPEN c1;
    LOOP
        FETCH c1 INTO l_sale_date;
        EXIT WHEN c1%NOTFOUND;
        SELECT to_char(to_date(l_sale_date), 'DY') into temp_value from 
dual;
        IF l_sale_date LIKE '01-JAN-%' OR l_sale_date LIKE '21-JAN-%' OR 
           l_sale_date LIKE '18-FEB-%' OR l_sale_date LIKE '28-MAY-%' 
           OR l_sale_date LIKE '04-JUL-%' OR l_sale_date LIKE '03-SEP-%' OR 
           l_sale_date LIKE '08-OCT-%' OR l_sale_date LIKE '11-NOV-%' 
           OR l_sale_date LIKE '22-NOV-%' OR l_sale_date LIKE '25-DEC-%'  
THEN
            INSERT INTO Times values(l_sale_date,'Holiday');
        ELSE IF temp_value='MON' OR temp_value ='TUE' OR temp_value='WED' OR 
temp_value='THU' OR temp_Value='FRI' THEN
            INSERT INTO Times values(l_sale_date,'Weekday');
        ELSE
            INSERT INTO Time values(l_sale_date,'Weekend');
        END IF;
    END LOOP;
    CLOSE c1;
END;
/

但我不断收到以下错误:

行/列错误


20/1 PL/SQL:忽略 SQL 语句

20/13 PL/SQL:ORA-00942:表或视图不存在

我一直在研究这个问题,但无法弄清楚我的代码有什么问题导致错误。

【问题讨论】:

  • 20/13 PL/SQL: ORA-00942: table or view does not exist 在第 13 行:CURSOR c1 IS SELECT SALE_DATE FROM SALES; - 表 sales 不存在 - 错误消息很清楚。
  • @krokodilko:错误在第 20 行第 13 列,而不是相反。此外,行号从过程的第一行开始。假设IF 语句中的所有这些条件都在同一行,那么第 20 行就是INSERT INTO Time ... 行。这里的错误很明显:表名拼写错误。
  • 问题标题中的错误信息与问题中的错误信息不同。你解决了这个问题吗?

标签: oracle plsql


【解决方案1】:

ORA-00942: 表或视图不存在

你有一个错字:第三个 INSERT 语句是

INSERT INTO Time 

而其他语句是

INSERT INTO Times 

您的问题标题中的错误有不同的原因:

遇到符号“文件结束”错误

表示语法错误。这一行

ELSE IF

告诉 PL/SQL 编译器您正在创建一个嵌套的 IF 语句。因此,它期望 END IF 与该 IF 以及外部块的 END IF 相匹配。像这样:

IF l_sale_date LIKE '01-JAN-%' 
    ...
ELSE IF temp_value='MON' 
      ...
     ELSE -- this goes with the nested IF
     ...
     END IF;  -- this goes with the nested IF
END IF;  -- this is the clause you're missing

但是,您似乎只是在尝试实现标准的一级开关。在这种情况下,您需要知道 PL/SQL 是 ELSIF 而不是 ELSE IF。就像这样:

IF l_sale_date LIKE '01-JAN-%' 
    ...
ELSIF temp_value='MON' 
      ...
ELSE -- this goes with the starting IF
     ...
END IF; 

或者,您可能希望使用 CASE 语句,它具有相同的结构,但更符合其他编程语言。

CASE
   WHEN l_sale_date LIKE '01-JAN-%' 
    ...
   WHEN temp_value='MON' 
      ...
   ELSE
     ...
END CASE;

【讨论】:

    【解决方案2】:

    这是一个固定版本 - times 不是 timeto_char 不是 to_dateelsif 不是 else if 等)。我还将它更改为使用游标 FOR 循环而不是所有打开、获取和关闭,将 temp_value 移动到游标中并给它一个正确的名称(语义是这项工作中的一切),并替换了 or使用方便的in () 构造列出。而且由于您刚开始,您甚至可以避免养成使用大写字母编码的习惯,这对我们的行业造成了可悲的影响。

    create or replace procedure time_procedure
    as
    begin
        for r in (
            select sale_date, to_date(sale_date, 'DY') as day_name
            from   sales
        )
        loop
            if r.sale_date like '01-JAN-%'
                or r.sale_date like '21-JAN-%'
                or r.sale_date like '18-FEB-%'
                or r.sale_date like '28-MAY-%'
                or r.sale_date like '04-JUL-%'
                or r.sale_date like '03-SEP-%'
                or r.sale_date like '08-OCT-%'
                or r.sale_date like '11-NOV-%'
                or r.sale_date like '22-NOV-%'
                or r.sale_date like '25-DEC-%'
            then
                insert into times(sale_day, day_type)
                values (r.sale_date, 'Holiday');
    
            elsif r.day_name in ('MON','TUE','WED','THU','FRI') then
                insert into times(sale_day, day_type)
                values (r.sale_date, 'Weekday');
    
            else
                insert into times(sale_day, day_type)
                values (r.sale_date,'Weekend');
            end if;
        end loop;
    end;
    

    但是,您永远不应该假设日期格式或语言。有一天,该程序可能会被具有西班牙语桌面设置的人调用,周末将是“SÁB”和“DOM”而不是“SAT”和“SUN”,默认日期格式可能是YYYY-MM-DD 或其他否则。

    另外,如果我们将日期名称缩短为一个字母并指定英文,那么周末日期就是'S',所以这是一个重构版本:

    create or replace procedure time_procedure
    as
    begin
        for r in (
            select sale_date
                 , to_char(sale_date,'DD-MM') as date_str
                 , substr(to_char(sale_date, 'DY', 'nls_date_language = English'),1,1) as day_name
            from   sales
        )
        loop
            if r.date_str in
                ( '01-01'
                , '21-01'
                , '18-02'
                , '28-05'
                , '04-07'
                , '03-09'
                , '08-10'
                , '11-11'
                , '22-11'
                , '25-12' )
            then
                insert into times(sale_day, day_type)
                values (r.sale_date, 'Holiday');
    
            elsif r.day_name = 'S' then
                insert into times(sale_day, day_type)
                values (r.sale_date,'Weekend');
    
            else
                insert into times(sale_day, day_type)
                values (r.sale_date, 'Weekday');
            end if;
        end loop;
    end;
    

    如果这不是 PL/SQL 的学习练习,您可以在 SQL 中完成所有事情:

    insert into times(sale_day, day_type)
    select sale_date
         , case when to_char(sale_date,'DD-MM') in
               ( '01-01', '21-01', '18-02', '28-05', '04-07', '03-09', '08-10', '11-11', '22-11', '25-12' )
               then 'Holiday'
           when to_char(sale_date, 'DY', 'nls_date_language = English') like 'S%'
               then 'Weekend'
           else
               'Weekday'
           end as day_type
    from   sales;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多