错误:PL/SQL:编译单元分析已终止?

Posted

技术标签:

【中文标题】错误:PL/SQL:编译单元分析已终止?【英文标题】:Error: PL/SQL: Compilation unit analysis terminated? 【发布时间】:2016-11-04 19:53:47 【问题描述】:

两个代码都出现同样的错误!!

DROP TABLE Date_Dimension CASCADE CONSTRAINTS ;

CREATE TABLE Date_Dimension
  (
    date_key             NUMBER NOT NULL ,
    full_date            DATE ,
    day_of_week          NUMBER ,
    day_num_in_month     NUMBER ,
    day_num_overall      NUMBER ,
    day_name             VARCHAR2 (9) ,
    day_abbrev           VARCHAR2 (3) ,
    week_num_in_year     NUMBER ,
    week_num_overall     NUMBER ,
    week_begin_date      DATE ,
    MONTH                NUMBER ,
    month_number_overall NUMBER ,
    month_name           VARCHAR2 (9) ,
    month_abbrev         VARCHAR2 (3) ,
    quarter              NUMBER ,
    YEAR                 VARCHAR2 (20) ,
    century              NUMBER
  ) ;
ALTER TABLE Date_Dimension ADD CONSTRAINT Date_Dimension_PK PRIMARY KEY ( date_key ) ;

Create or replace PROCEDURE sp_DATE_DIMENSION(v_STARTDATE IN INT, v_END_YEAR IN INT) IS

v_STARTDATE DATE;
v_ENDDATE DATE;

v_STARTDATE Date := to_date('2005/01/01' || v_START_YEAR, 'YYYY/MM/DD');
v_ENDDATE Date := to_date('2020/12/31' || v_END_YEAR,'YYYY/MM/DD');

BEGIN

INSERT INTO

  Date_Dimension 
  (date_key,full_date, day_of_week, day_num_in_month, day_num_overall, day_name, day_abbrev, week_num_in_year, week_num_overall, month, month_name, month_abbrev, quarter, year, century)

VALUES
  (
 '1',TO_DATE(v_STARTDATE, 'yyyy/mm/dd'), TO_NUMBER(v_STARTDATE, 'D'), TO_NUMBER(v_STARTDATE, 'DD'), TO_NUMBER(v_STARTDATE, 'DDD'), TO_CHAR(v_STARTDATE, 'DAY'), TO_CHAR(v_STARDATE, 'DY'), TO_NUMBER(v_STARTDATE, 'IW'), TO_NUMBER(v_STARTDATE, 'WW'), TO_NUMBER(v_STARTDATE, 'MM'), TO_CHAR (v_STARTDATE, 'MONTH'), TO_CHAR (v_STARTDATE, 'MON'), TO_NUMBER (v_STARTDATE, 'Q'), TO_CHAR (v_STARTDATE, 'YEAR'), TO_NUMBER (v_STARTDATE, 'CC') 
  )
;

IF v_STARTDATE > v_ENDDATE THEN

  DBMS_OUTPUT.PUT_LINE ('ERROR IN CODE REGARDING DATES CHOSEN');

ELSE

    WHILE v_STARTDATE <= V_ENDDATE LOOP 
        DBMS_OUTPUT.PUT_LINE ('Date : '||to_char(v_StartDate,'YYYY / MM / DD'));

        v_STARTDATE := v_STARTDATE + 1;

    END LOOP;
END IF;
END;

【问题讨论】:

错误是什么,出现在哪里? 您使用的是哪个客户端?除了初始终止消息之外,应该有一些方法可以查看引发的实际错误 - 可能在 IDE 的另一个窗口或部分中;或通过 SQL*Plus'show errors 之类的东西;或者通过查询user_errors 作为备用,它包含针对所有存储的 PL/SQL 代码的所有未解决的错误。如果你能看到那个,你应该也能看到其他错误...... Oracle SQL Developer 返回错误消息,不允许我查看错误的确切位置 SQL Developer 在编译器日志窗口中显示 PLS-00410,或者如果您在工作表中显示 show errors。它指向该错误的第 1 行 - 我猜它基本上放弃了尝试解析 PL/SQL。错误信息是可用的,然后你只需要解释它 *8-) 感谢 问题似乎已解决!感谢所有帮助 【参考方案1】:

你的代码得到

PLS-00410:RECORD、TABLE 或参数列表中不允许重复字段

您已将过程格式参数列表中的名称startdate 复制为局部变量;然后又重复了一遍。我认为您的意思是正式的论点只是年份,因为它是一个数字。您转换为日期也是错误的:

to_date('2005/01/01' || v_START_YEAR, 'YYYY/MM/DD')

...没有意义,因为您已经硬编码了 2005 年。

我认为对于那部分你想要的东西更像:

create or replace PROCEDURE sp_DATE_DIMENSION(p_START_YEAR IN NUMBER, p_END_YEAR IN NUMBER) IS
  l_START_DATE Date := to_date(p_START_YEAR ||'-01-01', 'YYYY-MM-DD');
  l_END_DATE Date := to_date(p_END_YEAR ||'-01-01', 'YYYY-MM-DD');
BEGIN

调整其他变量引用以匹配。在您的插入中,您将第一个值作为字符串'1' 而不是数字1 传递。然后针对已经过时的变量调用to_date();并且您使用日期元素的格式掩码调用to_number() - 对于您需要转换为字符串然后转换为数字的那些。这样插入会变得更像:

  INSERT INTO Date_Dimension (date_key, full_date, day_of_week, day_num_in_month,
    day_num_overall, day_name, day_abbrev, week_num_in_year, week_num_overall,
    month, month_name, month_abbrev, quarter, year, century)
  VALUES (1,
    l_START_DATE,
    TO_NUMBER(TO_CHAR(l_START_DATE, 'D')),
    TO_NUMBER(TO_CHAR(l_START_DATE, 'DD')),
    TO_NUMBER(TO_CHAR(l_START_DATE, 'DDD')),
    TO_CHAR(l_START_DATE, 'DAY'),
    TO_CHAR(l_START_DATE, 'DY'),
    TO_NUMBER(TO_CHAR(l_START_DATE, 'IW')),
    TO_NUMBER(TO_CHAR(l_START_DATE, 'WW')),
    TO_NUMBER(TO_CHAR(l_START_DATE, 'MM')),
    TO_CHAR(l_START_DATE, 'MONTH'),
    TO_CHAR(l_START_DATE, 'MON'),
    TO_NUMBER(TO_CHAR(l_START_DATE, 'Q')),
    TO_CHAR (l_START_DATE, 'YEAR'),
    TO_NUMBER(TO_CHAR(l_START_DATE, 'CC'))
  );

dbms_output 用于错误消息并不是一个好习惯,因为 (a) 调用程序没有其他指示出现问题,并且 (b) 即使在简单的客户端调用中,用户也可能不会已启用捕获或显示。最好抛出异常:

  IF l_START_DATE > l_END_DATE THEN
    RAISE_APPLICATION_ERROR (-20001, 'ERROR IN CODE REGARDING DATES CHOSEN');
  END IF;

  WHILE l_START_DATE <= l_END_DATE LOOP
    DBMS_OUTPUT.PUT_LINE ('Date : ' || to_char(l_START_DATE, 'YYYY / MM / DD'));
    l_START_DATE := l_START_DATE + 1;
  END LOOP;
END;
/

该异常将导致程序提前终止,因此您不需要 else 部分,因为如果日期错误,则无论如何都不会到达。

即便如此,您可能真的想在循环内进行插入,以便创建所有相关行;并且在一开始就进行检查和异常抛出是有意义的(也许比较年份而不是日期,但这并不重要。可能还有其他我已经忘记的事情 - 希望这会让你更倾向于正确的轨道。你真的不需要为此的过程,甚至 PL/SQL,因为它可以在纯 SQL 和单个插入中完成,但希望这是一个练习。

【讨论】:

以上是关于错误:PL/SQL:编译单元分析已终止?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 终止会话过程

将PL/SQL代码封装在机灵的包中

Oracle Database 19c 技术架构

Oracle Database 19c 技术架构

Windows 64位 安装Oracle instantclient 官方绿色版和PL/SQL Developer 总结

在使用 Entity Framework 数据库优先在表上插入行之前,如何从 PL/SQL 执行触发器?