Search code examples
oracle-databaseoracle11gplsql-package

Sql Command not properly ended//


It displays sql command not properly ended

PROCEDURE getCalendar (
V_Year VARCHAR2, V_Month VARCHAR2, V_LoginId varchar2, curAttendanceDate OUT T_CURSOR )

AS
   
      V_Date  DATE := TO_DATE (V_Year || '-' || V_Month || '-01', 'yyyy-mm-dd');
   BEGIN 
    
    
  Insert into T_ATTENDANCE_ATTENDANCE (LoginId, AttendanceDate,ShiftName, ShiftStartTime, ShiftEndTime, Active, AttendanceStatus)
     
   WITH DaysInMonth (dates) AS 
(
  SELECT V_Date FROM   DUAL 
  UNION ALL
  SELECT dates + INTERVAL '1' DAY
  FROM   DaysInMonth
  WHERE  dates + INTERVAL '1' DAY < ADD_MONTHS(TRUNC(V_Date, 'MONTH'), 1))
  select u.LoginID, d.dates, '' , null, null, 1, 'Approved' from daysinmonth d, T_ATTENDANCE_USER_MASTER U
  where loginid = V_LoginId
  and extract(month from dates) = extract(month from V_date) 
  and not Exists (select LoginId from T_ATTENDANCE_ATTENDANCE where LoginId = V_LoginId
  AND EXTRACT(YEAR FROM ATTENDANCEDATE) = extract(year from V_date) AND 
  EXTRACT(MONTH FROM AttendanceDate) = extract(month from V_date) AND ACTIVE = 1 );
  
   
     
   V_Date := INTERVAL '1' MONTH + V_Date;
   
WITH DaysInMonth (dates) AS 
  (
  SELECT V_Date FROM   DUAL 
  UNION ALL
  SELECT dates + INTERVAL '1' DAY
  FROM   DaysInMonth
  WHERE  dates + INTERVAL '1' DAY < ADD_MONTHS(TRUNC(V_Date, 'MONTH'), 1))
  select dates from DaysInMonth;
  
  
  Insert into T_ATTENDANCE_ATTENDANCE (LoginId, AttendanceDate,ShiftName, ShiftStartTime, ShiftEndTime, Active, AttendanceStatus)
         Select u.LoginID, d.dates, '',null, null, 1, 'Approved'  from DaysInMonth d cross join T_ATTENDANCE_USER_MASTER u 
     where extract(month from dates) = extract(month from V_date)  and LoginId = V_LoginId  and 
     not Exists (select LoginId from T_ATTENDANCE_ATTENDANCE where LoginId = V_LoginId AND 
     EXTRACT(YEAR FROM ATTENDANCEDATE) = extract(year from V_date) 
     AND EXTRACT(MONTH FROM AttendanceDate) = extract(month from V_date) AND ACTIVE = 1 );
     
     
    SELECT AttendanceDate, ShiftName, 
    TO_CHAR(AttendanceDate,'ddd') Day, 
    V_YEAR, V_MONTH , 
    To_char(SignIn, 'yyyy-MM-dd hh:mm:ss tt') SignIn, 
    To_char(SignOut, 'yyyy-MM-dd hh:mm:ss tt') SignOut FROM T_ATTENDANCE_ATTENDANCE
        WHERE LoginId = V_LoginId AND EXTRACT(YEAR FROM ATTENDANCEDATE) = V_Year 
    AND EXTRACT(MONTH FROM AttendanceDate) = V_Month
        AND ACTIVE = 1 ;

UPDATE a
           SET a.shiftname =
                  (SELECT CASE
                             WHEN     TO_CHAR (TO_DATE (a.attendancedate), 'DAY') IN
                                         ('SATURDAY')
                                  AND a.week IN (2, 4)
                             THEN
                                'WEEKLYOFF'
                             WHEN TO_CHAR (TO_DATE (a.attendancedate), 'WW') IN
                                     ('SUNDAY')
                             THEN
                                'WEEKLYOFF'
                             ELSE
                                'GENERAL1'                          END
                     FROM (SELECT attendancedate,
                                  shiftname,
                                   ROW_NUMBER ()
                                      OVER (
                                         PARTITION BY TO_CHAR (
                                                         TO_DATE (attendancedate, 'DAY'))
                                        ORDER BY attendancedate) AS week
                            FROM T_ATTENDANCE_ATTENDANCE  a1                                  LEFT JOIN T_ATTENDANCE_USER_MASTER u
                                     ON u.loginid = a1.loginid
                                   LEFT JOIN T_ATTENDANCE_EMPLOYEE_MASTER e
                                     ON e.empid = u.empid
                            WHERE     a1.loginid = V_loginid
                                   AND e.company IS NULL
                                   AND EXTRACT (YEAR FROM attendancedate) =
                                       EXTRACT (YEAR FROM SYSDATE)
                                  AND EXTRACT (MONTH FROM attendancedate) =
                                      EXTRACT (MONTH FROM SYSDATE)
                                  AND NVL (shiftname, 'x') = 'x') a )
                                   ORDER BY AttendanceDate;


end getCalendar;


---It displays sql command not properly ended--

CREATE TABLE "PROMETHEAN"."T_ATTENDANCE_ATTENDANCE" ( "ATTENDANCEID" NUMBER GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE, "LOGINID" VARCHAR2(200 BYTE) NOT NULL ENABLE, "ATTENDANCEDATE" TIMESTAMP (3), "SHIFTNAME" VARCHAR2(50 BYTE), "SHIFTSTARTTIME" TIMESTAMP (3), "SHIFTENDTIME" TIMESTAMP (3), "SIGNIN" TIMESTAMP (3), "SIGNOUT" TIMESTAMP (3), "OLDATTENDANCEID" NUMBER(10,0), "ACTIVE" NUMBER(10,0), "REMARK" VARCHAR2(255 BYTE), "ATTENDANCESTATUS" VARCHAR2(20 BYTE), "L1APPROVEDDBY" VARCHAR2(20 BYTE), "L1APPROVEDON" TIMESTAMP (3), "L2APPROVEDBY" VARCHAR2(20 BYTE), "L2APPROVALON" TIMESTAMP (3), "CREATEDBY" VARCHAR2(20 BYTE), "CREATEDON" TIMESTAMP (3), "MODIFIEDBY" VARCHAR2(20 BYTE), "MODIFIEDON" TIMESTAMP (3), "IPADDRESS" VARCHAR2(100 BYTE), "LOGONUSERNAME" VARCHAR2(100 BYTE), "COMPOFFDATE" DATE, "WORKLOCATIONTYPE" VARCHAR2(10 BYTE), "WORKLOCATION" VARCHAR2(50 BYTE), PRIMARY KEY ("ATTENDANCEID")


Solution

  • You asked about this in your previous question.

    Which told you that:

    Among other errors, you cannot use a SELECT statement on its own in PL/SQL. You need to SELECT ... [BULK COLLECT] INTO ....

    You also cannot use (excluding the fact that the ORDER BY clause is an error):

    UPDATE a
    SET a.shiftname = (SELECT value
                       FROM   table_name a)
    

    As the alias a is unknown in the outer query and I am assuming that you do not have a table named a.

    You can probably simplify your procedure to use a single MERGE statement that inserts 2 months data at once (rather than two 1-month inserts) and also calculates the week number to set the shift name in the INSERT (rather than requiring a subsequent UPDATE):

    CREATE PACKAGE BODY package_name AS
    
    PROCEDURE getCalendar (
      V_Year VARCHAR2,
      V_Month VARCHAR2,
      V_LoginId varchar2,
      curAttendanceDate OUT T_CURSOR
    )
    
    AS
      V_Date  DATE := TO_DATE (V_Year || '-' || V_Month || '-01', 'yyyy-mm-dd');
    BEGIN
      MERGE INTO T_ATTENDANCE_ATTENDANCE dst
      USING (
        WITH DaysInMonth (dates) AS (
          SELECT V_Date FROM   DUAL 
        UNION ALL
          SELECT dates + INTERVAL '1' DAY
          FROM   DaysInMonth
          WHERE  dates + INTERVAL '1' DAY < ADD_MONTHS(TRUNC(V_Date, 'MONTH'), 2)
        )
        SELECT u.LoginID,
               d.dates,
               (TRUNC(d.dates, 'IW') - a.start_date) / 7 AS week
        FROM   daysinmonth d
               CROSS JOIN T_ATTENDANCE_USER_MASTER U
               CROSS JOIN LATERAL (
                 SELECT TRUNC(COALESCE(MIN(attendancedate), v_date), 'IW') AS start_date
                 FROM   T_ATTENDANCE_ATTENDANCE a
                 WHERE  u.loginid = a.loginid
               ) a
        WHERE  loginid = V_LoginId
      ) src
      ON (dst.loginid = src.loginid AND dst.attendancedate = src.dates)
      WHEN NOT MATCHED THEN
        INSERT (
          LoginId,
          AttendanceDate,
          ShiftName,
          ShiftStartTime,
          ShiftEndTime,
          Active,
          AttendanceStatus
        ) VALUES (
          src.loginid,
          src.dates,
          CASE
          WHEN (   TRUNC(src.dates) - TRUNC(src.dates, 'IW') = 5
               AND MOD(src.week, 4) IN (1, 3) -- Change from 1-indexed weeks to 0-indexed.
               )
          OR   TRUNC(src.dates) - TRUNC(src.dates, 'IW') = 6
          THEN 'WEEKLYOFF'
          ELSE 'GENERAL1'
          END,
          NULL,
          NULL,
          1,
          'Approved'
        );
    end getCalendar;
    
    END;
    /
    

    However, your logic for calculating weeks is not well defined so this is mostly just a template for how you could implement it and you will need to make sure the logic is correct.

    fiddle