我总是在使用 CTE 时遇到错误,而不是问题所在

问题描述 投票:0回答:1

我无法编译下面的存储过程,并且我总是在 CTE(WITH DAYSINMONTH)附近遇到错误

我正在使用加入DAYSINMONTH

PROCEDURE getCalendar 
(        
    V_Year                 VARCHAR2,
    V_Month                VARCHAR2,
    V_LoginId varchar2,
    curAttendanceDate OUT T_CURSOR,
     res OUT SYS_REFCURSOR,
     sud OUT SYS_REFCURSOR,
     cur2 OUT SYS_REFCURSOR,
     cur OUT SYS_REFCURSOR
     
)
AS
 V_date Date:= TO_DATE (V_Year+V_Month+'01', 'yyyy-mm-dd');
--V_Date Date := TO_DATE (V_Year || '-' || V_Month || '-01', 'yyyy-mm-dd');

BEGIN
*****--I am always getting errror on with CTE DaysinMonth kindly help me to resolve.------------*****

WITH DaysInMonth (dates)
AS 
(
SELECT V_Date AS dates FROM   DUAL
UNION ALL
 SELECT dates + INTERVAL '1' DAY
 FROM   DaysInMonth
WHERE  dates + INTERVAL '1' DAY < ADD_MONTHS(TRUNC(V_Date, 'MONTH'), 1)
) 

                               
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);
                                                    
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);
                              
                              
V_Date := INTERVAL '1' MONTH + V_Date;


************--I am always getting errror on with CTE DaysinMonth kindly help me to resolve.--

WITH DaysInMonth (dates) AS 
(
  SELECT V_Date AS dates 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;                              

OPEN curAttendanceDate FOR
SELECT AttendanceDate,ShiftName,  TO_CHAR (AttendanceDate, 'ddd') cDAY,  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          
  ORDER BY AttendanceDate ASC;                
            
  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
  );

END getCalendar;
oracle plsql oracle11g
1个回答
0
投票

子查询分解子句(又名 CTE)NOT会创建一个可以在多个语句中重复使用的临时表。

您需要在使用子查询分解子句的每个语句中定义子查询分解子句。

您不能在 PL/SQL 中单独使用

SELECT
语句。您需要将其选择到光标中或使用
SELECT ... [BULK COLLECT] INTO ...

类似(未经测试,因为我们没有您的桌子):

PROCEDURE getCalendar 
(        
    V_Year                 VARCHAR2,
    V_Month                VARCHAR2,
    V_LoginId varchar2,
    curAttendanceDate OUT T_CURSOR,
     res OUT SYS_REFCURSOR,
     sud OUT SYS_REFCURSOR,
     cur2 OUT SYS_REFCURSOR,
     cur OUT SYS_REFCURSOR
     
)
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 AS dates 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,    -- '' is identical to NULL
         NULL,
         NULL,
         1,
         'Approved'
  FROM   DaysInMonth d
         CROSS JOIN T_ATTENDANCE_USER_MASTER u
  WHERE  LoginId = V_LoginId
  AND    NOT EXISTS (
           SELECT LoginId
           FROM   T_ATTENDANCE_ATTENDANCE
           WHERE  LoginId = V_LoginId
           AND    attendancedate >= d.dates
           AND    attendancedate <  d.dates + 1
           AND    ACTIVE = 1
        );
                                                    
  V_Date := ADD_MONTHS(V_Date, 1);

  -- You never use DaysInMonth after this and can just delete the (invalid)
  -- query from here.

  OPEN curAttendanceDate FOR
    SELECT AttendanceDate,
           ShiftName,
           TO_CHAR (AttendanceDate, 'ddd') cDAY,
           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          
    ORDER BY AttendanceDate ASC;                
            
  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
  );

END getCalendar;
/
© www.soinside.com 2019 - 2024. All rights reserved.