从日期属性中提取日期

Extract Date from a date attribute

所以我有这个table--

create table orders (
ono      number(5) not null primary key,
cno      number(5) references customers,
eno      number(4) references employees,
received date,
shipped  date);

填充了下面的脚本--

insert into orders values
(1020,1111,1000,'10-DEC-11','12-DEC-11');
insert into orders values
(1021,1111,1000,'12-JAN-12','15-JAN-12');
insert into orders values
(1022,2222,1001,'13-FEB-12','20-FEB-12');
insert into orders values
(1023,3333,1000,'12-MAR-12',null);

现在我正在尝试创建一个 PL/SQL Procedure,它将输入作为月份并显示该特定月份的订单。看来我只是不能把 EXTRACT() 弄对。这是我的代码块

CREATE OR REPLACE PROCEDURE TEST_REPORT
    (MONTH_NUMBER IN NUMBER )

    AS
     V_MONTH VARCHAR2(10);
    BEGIN

    SELECT RECEIVED INTO V_MONTH
    FROM ORDERS WHERE EXTRACT(MONTH FROM TO_DATE(
    ORDERS.RECEIVED, 'DD-MON-RR'))=MONTH_NUMBER;
    END TEST_REPORT;

我在这里做错了什么?作为记录,它编译并执行但不显示任何内容。

非常感谢

尝试 2

CREATE OR REPLACE PROCEDURE TEST_REPORT
    (MONTH_NUMBER IN NUMBER )

DECLARE
   CURSOR C1 IS SELECT RECEIVED INTO V_MONTH
   FROM ORDERS
   WHERE EXTRACT(MONTH FROM ORDERS.RECEIVED) = MONTH_NUMBER;
   V_DATE ORDERS.RECEIVED%TYPE;
BEGIN

     OPEN C1;
  LOOP
    FETCH C1 INTO V_DATE;
    IF C1%FOUND THEN  -- fetch succeeded
      DBMS_OUTPUT.PUT_LINE('DATE ' || V_DATE);
    ELSE  -- fetch failed, so exit loop
      EXIT;
    END IF;
  END LOOP;
END TEST_REPORT;

由于 'received' 是 DATE 类型,您不应在其上使用 TO_DATE。 TO_DATE 用于将字符串(VARCHAR2)解析为日期格式。准确地说,它不应该给你带来麻烦,但我已经遇到过这种奇怪的行为。

替换以下查询:

SELECT RECEIVED INTO V_MONTH
  FROM ORDERS
 WHERE EXTRACT(MONTH FROM TO_DATE(ORDERS.RECEIVED, 'DD-MON-RR'))=MONTH_NUMBER;

有了这个:

SELECT RECEIVED INTO V_MONTH
  FROM ORDERS
 WHERE EXTRACT(MONTH FROM ORDERS.RECEIVED) = MONTH_NUMBER;
 DBMS_OUTPUT.PUT_LINE(V_MONTH); --Print your result.

有关 EXTRACT 的更多信息和示例,请参见 documentation

此外,您应该知道,如果符合您的查询的行不止一行,则会抛出异常,因为 v_month 是 VARCHAR2 类型。您应该考虑使用集合或迭代游标。 here.

可以找到一个完全符合您需要的隐式游标的简单示例

编辑:在我们的谈话之后,这里有一个针对您的案例的解决方案:

CREATE OR REPLACE PROCEDURE TEST_REPORT 
(MONTH_NUMBER IN NUMBER ) 

AS 
    CURSOR C1 IS SELECT RECEIVED 
                   FROM ORDERS 
                  WHERE EXTRACT(MONTH FROM ORDERS.RECEIVED) = MONTH_NUMBER; 
    V_DATE ORDERS.RECEIVED%TYPE; 
BEGIN 

    OPEN C1; 
    LOOP 
        FETCH C1 INTO V_DATE; 
        IF C1%FOUND THEN -- fetch succeeded 
            DBMS_OUTPUT.PUT_LINE('DATE ' || V_DATE); 
        ELSE -- fetch failed, so exit loop 
            EXIT; 
        END IF; 
    END LOOP; 
END TEST_REPORT;

Just a though in another way to handle multiple records, we can use BULK COLLECT as row-by-row processing is not at all recommended if data volume is huge. Huge data --more context switching. Let me know if this helps.

CREATE OR REPLACE PROCEDURE TEST_REPORT(
    MONTH_NUMBER IN NUMBER )
AS
TYPE v_rcvd
IS
  TABLE OF ORDERS.RECEIVED%TYPE;
  v_rcvd_tab v_rcvd;
BEGIN
  SELECT RECEIVED BULK COLLECT
  INTO v_rcvd_tab
  FROM ORDERS
  WHERE EXTRACT(MONTH FROM ORDERS.RECEIVED) = MONTH_NUMBER;
  IF v_rcvd_tab.EXISTS(1) THEN
    FOR I IN v_rcvd_tab.FIRST..v_rcvd_tab.LAST
    LOOP
      DBMS_OUTPUT.PUT_LINE('DATE ' || v_rcvd_tab(i));
    END LOOP;
  END IF;
END TEST_REPORT;