Coder101
Coder101

Reputation: 31

Error: PL/SQL: Compilation unit analysis terminated?

Keep Getting the same error on both codes!!

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;

Upvotes: 3

Views: 20449

Answers (1)

Alex Poole
Alex Poole

Reputation: 191275

Your code gets

PLS-00410: duplicate fields in RECORD,TABLE or argument list are not permitted

You have duplicated the name startdate from the procedure's format argument list as a local variable; and then repeated both of them again. I think you meant the formal argument to just be the year, since it's a number. Your conversion to a date is also then wrong:

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

... doesn't make sense, as you already have the year 2005 hard-coded.

I think for that part you want something more like:

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

with other variables references tweaked to match. In your insert you're passing the first value as the string '1' instead of the number 1. You then call to_date() against variables which are already dated; and you call to_number() with a format mask for a date element - for those you need to convert to a string, and then to a number. So that insert woudl become more like:

  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'))
  );

It isn't good practice to use dbms_output for error messages, as (a) a calling program has no other indication that something is wrong, and (b) even in a simple client call a user may well not even have capture or display of those enabled. It's better to throw an exception:

  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;
/

The exception will cause the procedure to terminate early, so you don't need the else part as nothing beyond that is reached anyway if the dates are wrong.

Even so, you probably really want to do the insert inside the loop so you create all the relevant rows; and it would make sense to do the check and exception throw right at the start (maybe comparing the years rather than the dates, but doesn't really matter. And probably other things I've forgotten - hopefully this will put you more towards the right track. You don't really need a procedure for this, or even PL/SQL, as it could be done in plain SQL and a single insert, but hopefully this is an exercise.

Upvotes: 1

Related Questions