【问题标题】:Extract Date from a date attribute从日期属性中提取日期
【发布时间】:2016-03-27 00:20:52
【问题描述】:

所以我有这张桌子--

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;

【问题讨论】:

  • 永远不要在 DATE 列上应用 TO_DATE。它强制 Oracle: 1. 首先将其转换为字符串 2. 然后根据特定于语言环境的 NLS 设置将其转换回日期。您需要 TO_DATE 将文字转换为日期。见stackoverflow.com/a/30332190/3989608

标签: oracle plsql oracle11g date-formatting date-arithmetic


【解决方案1】:

只是以另一种方式处理多条记录,我们可以使用 不建议将 BULK COLLECT 作为逐行处理,如果 数据量巨大。海量数据——更多的上下文切换。让我知道 如果这有帮助。

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;

【讨论】:

  • 这确实是一个更好的做法。我只是认为 id 从光标而不是集合开始会更容易,但这是一个很好的答案!
【解决方案2】:

由于 '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;

【讨论】:

  • 您好 Neria,谢谢...如果我尝试 EXECUTE TEST_REPORT(01)ORA-01422: exact fetch returns more than requested number of rows 尝试 EXECUTE TEST_REPORT(03) 时仍然没有输出
  • 我刚刚在我的回答中添加了另一部分。
  • 是的,我确实希望返回不止一行。我该如何处理呢?
  • 在此处查看示例 6-14,它完全符合您的需求:docs.oracle.com/cd/B28359_01/appdev.111/b28370/…
  • 那是一个使用游标的PL/SQL。但是我怎样才能在这里实现它来确定我需要做什么呢?对不起,我是菜鸟。
猜你喜欢
  • 2023-03-24
  • 2019-03-20
  • 2014-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-23
  • 2011-02-17
  • 2019-02-24
相关资源
最近更新 更多