簡體   English   中英

PLSQL 將流水線函數的結果連接到表

[英]PLSQL join results of a pipelined function to a table

我有一些 SQL(見下文),效果很好。

INSERT INTO timeoff (employee_id,    timeoff_date)
SELECT
  e.employee_id,
  c.date_val
FROM   employees e
  INNER JOIN table(
    generate_dates_pipelined(date '2021-08-01', DATE '2021-08-10')
  ) 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;

我正在嘗試創建一個將插入數據的函數,因為我想擺脫 SQL 中的硬編碼日期。

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

函數中的代碼在 SQL 中運行良好(見上文)。 當我嘗試將其移植到某個過程時,出現語法錯誤。 我相信問題在於連接我的流水線函數的結果,這對員工表工作正常。 我不確定如何解決這個問題。

下面是我的測試用例。 我正在實時 sql 中進行測試,因此我們可以擁有相同的 Oracle 版本。 由於我是 PLSQL 新手,有人可以建議如何解決此問題。 在此先感謝所有答案。

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



--  testing 

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
    e.employee_id,
    c.date_val
  FROM   employees e
    INNER JOIN ON
      BULK COLLECT INTO l_res
      FROM 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');

您將 BULK COLLECT INTO 置於一個非常奇怪的位置。 我沒有檢查你的語句邏輯是否正確,而是更正了語法錯誤。

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
     ;


/**
      SELECT e.employee_id,
     c.date_val
     FROM   employees e
      INNER JOIN ON
     BULK COLLECT INTO l_res
      FROM 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;

輸出

03-AUG-21
04-AUG-21
06-AUG-21
07-AUG-21
10-AUG-21
03-AUG-21
04-AUG-21
06-AUG-21
07-AUG-21
10-AUG-21
03-AUG-21
04-AUG-21
06-AUG-21
07-AUG-21
10-AUG-21
03-AUG-21
04-AUG-21
06-AUG-21
07-AUG-21
10-AUG-21

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM