PLSQL 需要 REFCURSOR DATE + TIME

PLSQL Need REFCURSOR DATE + TIME

我正在使用这段代码,我遇到了 1 个问题,o_besteltijden 游标将其作为输出:01-06-15(一个日期),但我更喜欢这样的输出:16:00(所以只有时间)或 01-06-15 16:00:00(日期 + 时间)。那可能吗?

SET SERVEROUTPUT ON;
CREATE OR REPLACE TYPE t_openingstijd IS TABLE OF DATE;

CREATE OR REPLACE PROCEDURE zoekMogelijkeBesteltijden(p_winkelId IN INTEGER, p_datum IN DATE, p_periode IN INTEGER DEFAULT 21, p_bezorgen IN BOOLEAN,
                                                  o_open OUT BOOLEAN, o_besteltijden OUT SYS_REFCURSOR)
AS
v_foundWinkel NUMBER := 0;
v_winkel Winkel%ROWTYPE;

TYPE arrayVarchar IS VARRAY(7) OF VARCHAR2(2);
v_dagen arrayVarchar := arrayVarchar('ma', 'di', 'wo', 'do', 'vr', 'za', 'zo');

CURSOR v_openingstijden(p_id IN NUMBER, p_dag IN VARCHAR2) IS
    SELECT * FROM Openingstijd
    WHERE winkel_id = p_id
    AND dag = p_dag;

v_besteltijden t_openingstijd := t_openingstijd();

v_eindUur NUMBER := 0;
v_eindMinuten NUMBER := 0;

v_beginUur NUMBER := 0;
v_beginMinuten NUMBER := 0;

-- Exceptions
v_winkelNotFound EXCEPTION;
BEGIN
-- Kijken of winkel wel bestaat.
SELECT COUNT(1) INTO v_foundWinkel
FROM Winkel
WHERE id = p_winkelId;

IF(v_foundWinkel = 0) THEN
    RAISE v_winkelNotFound;
END IF;

-- Alle data krijgen van de winkel. Exclusief de openingstijden, producten en coupons.
SELECT * INTO v_winkel
FROM Winkel
WHERE id = p_winkelId;

FOR i_tijd IN v_openingstijden(p_winkelId, 
                               v_dagen(TO_NUMBER(TO_CHAR(p_datum, 'D')))) LOOP        

    -- Instellen van huidige tijd om mee door te lopen.
    v_eindUur := TO_NUMBER(TO_CHAR(i_tijd.gesloten, 'HH24'));

    IF(p_bezorgen = true) THEN
        IF(TO_NUMBER(TO_CHAR(i_tijd.gesloten, 'MI')) < 30) THEN
            IF(TO_NUMBER(TO_CHAR(i_tijd.gesloten, 'MI')) < 15) THEN
                v_eindMinuten := 30;
            ELSE
                v_eindMinuten := 45;
            END IF;

            v_eindUur := v_eindUur - 1;
        ELSE
            IF(TO_NUMBER(TO_CHAR(i_tijd.gesloten, 'MI')) < 45) THEN
                v_eindMinuten := 0;
            ELSE
                v_eindMinuten := 15;
            END IF;
        END IF;
    ELSE
        IF(TO_NUMBER(TO_CHAR(i_tijd.gesloten, 'MI')) < 15) THEN
            v_eindMinuten := 45;
            v_eindUur := v_eindUur - 1;
        ELSE
            IF(TO_NUMBER(TO_CHAR(i_tijd.gesloten, 'MI')) < 30) THEN
                v_eindMinuten := 0;
            ELSIF(TO_NUMBER(TO_CHAR(i_tijd.gesloten, 'MI')) < 45) THEN
                v_eindMinuten := 15;
            ELSE
                v_eindMinuten := 30;
            END IF;
        END IF;    
    END IF;

    -- Begin tijd berekenen
    v_beginUur := TO_NUMBER(TO_CHAR(i_tijd.open, 'HH24'));

    IF(TO_NUMBER(TO_CHAR(i_tijd.open, 'MI')) < 15) THEN
        v_beginMinuten := 0;
    ELSIF(TO_NUMBER(TO_CHAR(i_tijd.open, 'MI')) < 30) THEN
        v_beginMinuten := 15;
    ELSIF(TO_NUMBER(TO_CHAR(i_tijd.open, 'MI')) < 45) THEN
        v_beginMinuten := 30;
    ELSE
        v_beginMinuten := 45;
    END IF;

    -- Eerste uur vol maken.
    IF(v_beginMinuten != 0) THEN
        FOR i IN 1 .. ((60 - v_beginMinuten) / 15) LOOP
            v_besteltijden.extend;
            v_besteltijden(v_besteltijden.count) := TO_DATE( v_beginUur || ':' || v_beginMinuten * i, 'HH24:MI');
        END LOOP;

        v_beginUur := v_beginUur + 1;
        v_beginMinuten := 0;
    END IF;

    -- Tot het laatste uur volmaken.
    IF(v_beginUur != v_eindUur) THEN
        FOR x IN 1 .. (v_eindUur - v_beginUur) LOOP
            FOR i IN 1 .. 4 LOOP
                v_besteltijden.extend;

                IF(i = 1) THEN
                    v_besteltijden(v_besteltijden.count) := TO_DATE( v_beginUur || ':00', 'HH24:MI');
                ELSE
                    v_besteltijden(v_besteltijden.count) := TO_DATE( v_beginUur || ':' || 15 * (i - 1), 'HH24:MI');
                END IF;
            END LOOP;

            v_beginUur := v_beginUur + 1;
        END LOOP;
    END IF;

    -- Laatste uur ook maar eens volmaken.
    IF(v_beginUur = v_eindUur AND v_eindMinuten >= v_beginMinuten) THEN
        FOR i IN 1 .. (v_eindMinuten / 15) + 1 LOOP
            v_besteltijden.extend;

            IF(i = 1) THEN
                v_besteltijden(v_besteltijden.count) := TO_DATE( v_beginUur || ':00', 'HH24:MI');
            ELSE
                v_besteltijden(v_besteltijden.count) := TO_DATE( v_beginUur || ':' || 15 * (i - 1), 'HH24:MI');
            END IF;
        END LOOP;
    END IF;

END LOOP;

-- Data terug in output cursor.
OPEN o_besteltijden FOR
    SELECT * FROM TABLE(CAST(v_besteltijden AS t_openingstijd));


-- Is de winkel momenteel open?
FOR i_openingstijd IN v_openingstijden(p_winkelId, 
                               v_dagen(TO_NUMBER(TO_CHAR(SYSDATE, 'D')))) LOOP  
    IF(o_open = true) THEN
        IF(TO_NUMBER(TO_CHAR(SYSDATE, 'HH24MI')) >= TO_NUMBER(TO_CHAR(i_openingstijd.open, 'HH24MI'))
          AND TO_NUMBER(TO_CHAR(SYSDATE, 'HH24MI')) <= TO_NUMBER(TO_CHAR(i_openingstijd.gesloten, 'HH24MI'))) THEN
            o_open := true;
        ELSE
            o_open := false;
        END IF;
    END IF;
END LOOP;

EXCEPTION
WHEN v_winkelNotFound THEN
    dbms_output.put_line('Winkel niet gevonden.');
END;
/

这里的问题好像是这样的:

  1. 您正在将 o_besteltijden 设置为从 CAST(v_besteltijden AS t_openingstijd) 中选择的值,其中 v_besteltijden 是根据 to_date

    [=30 计算得出的=]
  2. t_openingstijd 是日期类型 (CREATE OR REPLACE TYPE t_openingstijd IS TABLE OF DATE;) 的 table。所以你的答案将采用日期格式。

相反,如果您需要 timestamp 类型,则必须对这些变量进行更改并在其中存储 timestamp 以获得所需的输出 date+time or time through formatting.