Oracle
 sql >> Base de données >  >> RDS >> Oracle

Oracle créant une procédure appelant une fonction

Vous devez sélectionner le résultat que la fonction renvoie dans quelque chose . Quoi? Une variable locale, par exemple.

SQL> CREATE OR REPLACE PROCEDURE date_test (start_date DATE, end_date DATE)
  2  IS
  3     l_res  nt_Date;
  4  BEGIN
  5     SELECT generate_dates_pipelined (start_date, end_date)
  6       INTO l_res
  7       FROM DUAL;
  8
  9     FOR i IN l_res.FIRST .. l_res.LAST
 10     LOOP
 11        DBMS_OUTPUT.put_line (l_res (i).date_val);
 12     END LOOP;
 13  END;
 14  /

Procedure created.

SQL> set serveroutput on
SQL> EXEC date_test(DATE '2021-08-01', DATE '2021-08-10');
01.08.21
02.08.21
03.08.21
04.08.21
05.08.21
06.08.21
07.08.21
08.08.21
09.08.21
10.08.21

PL/SQL procedure successfully completed.

SQL>

[MODIFIER] Si vous souhaitez supprimer des dates qui existent dans le holiday table, alors c'est une option :utilisez le delete méthode de collecte.

Comme la collection est maintenant clairsemée, vous ne pouvez pas utiliser FOR boucle pour afficher ses valeurs (comme vous obtiendriez no_data_found erreur) - utilisez WHILE à la place.

SQL> CREATE OR REPLACE PROCEDURE date_test (start_date DATE, end_date DATE)
  2  IS
  3     l_res  nt_date;
  4     i      NUMBER;
  5     l_cnt  NUMBER;
  6  BEGIN
  7     SELECT generate_dates_pipelined (start_date, end_date)
  8       INTO l_res
  9       FROM DUAL;
 10
 11     DBMS_OUTPUT.put_line ('contents of L_RES (all dates) ------------');
 12
 13     FOR i IN l_res.FIRST .. l_res.LAST
 14     LOOP
 15        DBMS_OUTPUT.put_line (l_res (i).date_val);
 16     END LOOP;
 17
 18     DBMS_OUTPUT.put_line ('removing holidays -------------------------');
 19
 20     FOR i IN l_res.FIRST .. l_res.LAST
 21     LOOP
 22        SELECT MAX (1)
 23          INTO l_cnt
 24          FROM holidays
 25         WHERE holiday_date = l_res (i).date_val;
 26
 27        DBMS_OUTPUT.put_line (
 28           l_res (i).date_val || ': cnt = ' || l_cnt || ' - delete it!');
 29
 30        IF l_cnt = 1
 31        THEN
 32           l_res.delete (i);
 33        END IF;
 34     END LOOP;
 35
 36     DBMS_OUTPUT.put_line ('contents of L_RES (holidays excluded) ----');
 37
 38     i := l_res.FIRST;
 39
 40     WHILE i IS NOT NULL
 41     LOOP
 42        DBMS_OUTPUT.put_line (l_res (i).date_val);
 43        i := l_res.NEXT (i);
 44     END LOOP;
 45  END;
 46  /

Procedure created.

Regardez-le fonctionner :

SQL> SELECT * FROM holidays;

HOLIDAY_DA HOLIDAY_NAME
---------- --------------------
01.08.2021 August 01 2021
05.08.2021 August 05 2021

SQL> EXEC date_test(date '2021-08-01', date '2021-08-10');
contents of L_RES (all dates) ------------
01.08.2021
02.08.2021
03.08.2021
04.08.2021
05.08.2021
06.08.2021
07.08.2021
08.08.2021
09.08.2021
10.08.2021
removing holidays -------------------------
01.08.2021: cnt = 1 - delete it!
02.08.2021: cnt =  - delete it!
03.08.2021: cnt =  - delete it!
04.08.2021: cnt =  - delete it!
05.08.2021: cnt = 1 - delete it!
06.08.2021: cnt =  - delete it!
07.08.2021: cnt =  - delete it!
08.08.2021: cnt =  - delete it!
09.08.2021: cnt =  - delete it!
10.08.2021: cnt =  - delete it!
contents of L_RES (holidays excluded) ----
02.08.2021
03.08.2021
04.08.2021
06.08.2021
07.08.2021
08.08.2021
09.08.2021
10.08.2021

PL/SQL procedure successfully completed.

SQL>

[MODIFIER]

Si vous vouliez utiliser NOT EXISTS , alors voici comment procéder :

SQL> SELECT date_val
  2    FROM TABLE (
  3            generate_dates_pipelined (DATE '2021-08-01', DATE '2021-08-10'))
  4   WHERE NOT EXISTS
  5            (SELECT 1
  6               FROM holidays h
  7              WHERE date_val = h.holiday_date);

DATE_VAL
----------
02.08.2021
03.08.2021
04.08.2021
06.08.2021
07.08.2021
08.08.2021
09.08.2021
10.08.2021

8 rows selected.

SQL>