[英]Oracle procedure inserting multiple rows from result of query
我正在嘗試創建一個過程,該過程將根據過程中的查詢結果將多行插入到表中。
下面的設置工作正常,但我很難將查詢輸出中的 employee_id、timeoff_date 插入到 timeoff 表中。
下面是我的測試用例。 我正在實時 sql 中進行測試,因此我們可以擁有相同的 Oracle 版本。 任何幫助將不勝感激。
CREATE OR REPLACE TYPE obj_date IS OBJECT (
date_val DATE
);
CREATE OR REPLACE TYPE nt_date IS TABLE OF obj_date;
create or replace function generate_dates_pipelined(
p_from in date,
p_to in date
)
return nt_date
pipelined
is
begin
for c1 in (
with calendar (start_date, end_date ) as (
select trunc(p_from), trunc(p_to) from dual
union all
select start_date + 1, end_date
from calendar
where start_date + 1 <= end_date
)
select start_date as day
from calendar
) loop
pipe row (obj_date(c1.day));
end loop;
return;
end generate_dates_pipelined;
create table holidays(
holiday_date DATE not null,
holiday_name VARCHAR2(20),
constraint holidays_pk primary key (holiday_date),
constraint is_midnight check ( holiday_date = trunc ( holiday_date ) )
);
INSERT into holidays (HOLIDAY_DATE,HOLIDAY_NAME) WITH dts as (
select to_date('01-AUG-2021 00:00:00','DD-MON-YYYY HH24:MI:SS'), 'August 1st 2021' from dual union all
select to_date('05-AUG-2021 00:00:00','DD-MON-YYYY HH24:MI:SS'), 'August 5th 2021' from dual) SELECT * from dts;
Create table employees(
employee_id NUMBER(6),
first_name VARCHAR2(20),
last_name VARCHAR2(20),
card_num VARCHAR2(10),
work_days VARCHAR2(7)
);
ALTER TABLE employees
ADD ( CONSTRAINT employees_pk
PRIMARY KEY (employee_id));
INSERT INTO employees
(
EMPLOYEE_ID,
first_name,
last_name,
card_num,
work_days)
WITH names AS (
SELECT 1, 'Jane', 'Doe','F123456', 'NYYYYYN' FROM dual UNION ALL
SELECT 2, 'Madison', 'Smith','R33432','NYYYYYN'FROM dual UNION ALL
SELECT 3, 'Justin', 'Case','C765341','NYYYYYN'FROM dual UNION ALL
SELECT 4, 'Mike', 'Jones', 'D564311','NYYYYYN' FROM dual) SELECT * FROM names;
create table timeoff(
seq_num integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
employee_id NUMBER(6),
timeoff_date DATE,
timeoff_type VARCHAR2(1) DEFAULT 'V',
constraint timeoff_chk check (timeoff_date=trunc(timeoff_date, 'dd')),
constraint timeoff_pk primary key (employee_id, timeoff_date)
);
CREATE OR REPLACE PROCEDURE create_timeoff_requests (start_date DATE, end_date DATE)
IS
type t_date is table of date;
l_res t_date;
BEGIN
SELECT
c.date_val
BULK COLLECT INTO l_res
FROM employees e
INNER JOIN TABLE (generate_dates_pipelined (start_date, end_date))c
PARTITION BY ( e.employee_id )
ON (SUBSTR(e.work_days, TRUNC(c.date_val) - TRUNC(c.date_val, 'IW') + 1, 1) = 'Y')
WHERE NOT EXISTS (
SELECT 1
FROM holidays h
WHERE c.date_val = h.holiday_date
)
ORDER BY
e.employee_id,
c.date_val;
-- debug
-- for i in 1..l_res.count -- loop
--dbms_output.put_line(l_res(i));
-- end loop;
END;
EXEC create_timeoff_requests (DATE '2021-08-01', DATE '2021-08-10');
我認為創建一個看起來像這樣的過程可能更容易(只需用過程定義中的參數替換塊中聲明的常量):
CREATE PROCEDURE create_timeoff_requests
(
p_dStart DATE,
p_dEnd DATE,
p_nEmployeeID INTEGER
p_sType VARCHAR2
)
IS
BEGIN
INSERT INTO timeoff (employee_id, timeoff_date, timeoff_type)
SELECT e.employee_id, do.day_off, p_sType
FROM employees e
CROSS JOIN (SELECT p_dStart+LEVEL AS DAY_OFF
FROM DUAL
CONNECT BY LEVEL <= p_dEnd - p_dStart) do
WHERE e.employee_id = p_nEmployeeID
AND SUBSTR(e.workdays, TO_CHAR(do.day_off, 'D'), 1) = 'Y'
AND NOT EXISTS (SELECT 'X' FROM holidays h WHERE h.holiday_date = do.day_off);
END;
/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.