我无法编译下面的存储过程,并且我总是在 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;
子查询分解子句(又名 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;
/