使用 PL/SQL 的日期和条件

Posted

技术标签:

【中文标题】使用 PL/SQL 的日期和条件【英文标题】:Date and conditions using PL/SQL 【发布时间】:2015-12-23 20:24:51 【问题描述】:

我在下面的过程中遇到问题,因为每当我传递月份和年份的日期时,IF 条件会循环我的表中存在的记录数 - 只存在两行 - 它还显示了两种可能性.我还包括了结果来说明我的意思!

 PRODUCT_NUM   ORDER_NUM    QUANTITY        PRICE     MONTHLY_DATE
-------------- ----------- ------------- ------------ -------------
   12345         106           3             19.99     21-DEC-15   
   67894         107           1             19.99     21-DEC-15


 CREATE OR REPLACE PROCEDURE Proce_Name (Pram_Date DATE ) 
   AS
 BGIN
  FOR Y IN 
    (SELECT SUM(PRICE) AS TOTAL_AMOUNT, SUM(NVL(QUANTITY,0) * NVL (   
    (PRICE,0)) AS TOTAL, MONTHLY_DATE   
    FROM PRODUCTS
    GROUP BY MONTHLY_DATE 
    ORDER BY MONTHLY_DATE DESC) LOOP
    IF  TO_CHAR( Y.MONTHLY_DATE, 'mm-yyyy')= TO_CHAR(Pram_Date,'mm-yyyy') THEN
     DBMS_OUTPUT.PUT_LINE('TOTAL AMOUNT: '|| '  '|| Y.TOTAL_AMOUNT);
     DBMS_OUTPUT.PUT_LINE('');
     DBMS_OUTPUT.PUT_LINE('TOTAL: '|| '   '||  Y.TOTAL);
   ELSE
     DBMS_OUTPUT.PUT_LINE('No Data for this month');
   END IF;
  END LOOP;

END Proce_name;

调用块:

DECLARE
   MONTHLY_D DATE := TO_DATE('01-2012','mm-yyyy');
BEGIN
 Proce_Name(MONTHLY_D);
END;

/

这是我通过的日期与表中的记录匹配的时间:

     No Data for this month

     TOTAL AMOUNT:   4

     TOTAL:      99.96

当我传递一个表格中不存在的日期时,这里的结果:

     No Data for this month
     No Data for this month

如何更改我的程序以准确检查上述日期格式?

【问题讨论】:

【参考方案1】:

这里是代码,你也可以考虑异常处理: 很少观察,您可以将 prem_date 视为 char 它本身而不是传递日期。此外,如果数据集很大并且每月日期被索引,则应避免在每月日期上应用 to_char 条件。

CREATE OR REPLACE PROCEDURE Proce_Name (Pram_Date DATE )
   AS
  l_total_amount float;
  l_total float;
 BEGIN
    SELECT SUM(PRICE) AS TOTAL_AMOUNT,
     SUM(NVL(QUANTITY,0) * NVL(PRICE,0)) AS TOTAL
    INTO l_total_amount, l_total
    FROM PRODUCTS
    WHERE to_char(monthly_date, 'mm-yyyy') = to_char(pram_date, 'mm-yyyy');
    if(l_total_amount is not null) then
      DBMS_OUTPUT.PUT_LINE('TOTAL AMOUNT: '|| '  '|| L_TOTAL_AMOUNT);
      DBMS_OUTPUT.PUT_LINE('');
      DBMS_OUTPUT.PUT_LINE('TOTAL: '|| '   '||  L_TOTAL);
    else
      DBMS_OUTPUT.PUT_LINE('No Data for this month');
    end if;
END Proce_name;
/

【讨论】:

感谢您的回复,程序中条件不成立!而且我有不止一个结果,所以需要循环!【参考方案2】:

我有如下更新程序

CREATE OR REPLACE PROCEDURE get_sales_report(c_date date) AS
  l_amount number(18, 2);
  l_total  number(18, 2);
BEGIN
  begin
    SELECT SUM(PRICE), SUM(NVL(QUANTITY, 0) * NVL(PRICE, 0))
      into l_amount, l_total
      FROM product
     where TO_CHAR(MONTHLY_DATE, 'mm-yyyy') = to_char(c_date, 'mm-yyyy')
     GROUP BY TO_CHAR(MONTHLY_DATE, 'mm-yyyy')
     ORDER BY TO_CHAR(MONTHLY_DATE, 'mm-yyyy') DESC;

    DBMS_OUTPUT.PUT_LINE('TOTAL AMOUNT: ' || '  ' || l_amount);
    DBMS_OUTPUT.PUT_LINE('');
    DBMS_OUTPUT.PUT_LINE('TOTAL: ' || '   ' || l_total);
  exception
    when no_data_found then
      DBMS_OUTPUT.PUT_LINE('No Data for this month');
  END; -- end of exception
  -- add your code here
  -- add your code here
  -- add your code here
end;

也为 dbms_output 回显文本调用以下命令。

set serveroutput on size 30000;

将您的过程称为

declare
  c_date2 DATE := TO_DATE('12-2015','mm-yyyy');
begin
  get_sales_report(c_date2);
end;

【讨论】:

谢谢你的回答,还有保存问题!! 你能发布 PRODUCTS 表的创建语句并发布你用来调用 Proce_Name 过程的代码 sn-p 吗? 请看问题 好的。根据您的测试数据,我建议的代码块应该可以。请注意;我对 select 语句、order by 和 group by 进行了更改。你能在运行我的代码块后发布输出吗? 这是结果的复制/粘贴 - 此日期无销售 此日期无销售【参考方案3】:

日期是固定大小的类型。因此,如果要按整月分组,则必须将日期列查询为 char。意思是,您应该使用 TO_CHAR 而不是 TO_DATE。

这是(更简单的)方法(我的更改是小写的)-

CREATE OR REPLACE PROCEDURE Proce_Name (Pram_Date date) AS   
  l_month        char(7);
  l_total_amount number;
  l_total        number;
BEGIN
  SELECT to_char(monthly_date,'mm-yyyy') as month, 
          SUM(PRICE) AS TOTAL_AMOUNT, 
          SUM(NVL(QUANTITY,0)*NVL(PRICE,0)) AS TOTAL   
   INTO l_month, l_total_amount, l_total
   FROM PRODUCTS
   where to_char(monthly_date,'mm-yyyy')=to_char(Pram_Date, 'mm-yyyy')
   GROUP BY to_char(monthly_date,'mm-yyyy');

  if l_month is not null then
    DBMS_OUTPUT.PUT_LINE('TOTAL AMOUNT: '|| '  '|| Y.TOTAL_AMOUNT);
    DBMS_OUTPUT.PUT_LINE('');
    DBMS_OUTPUT.PUT_LINE('TOTAL: '|| '   '||  Y.TOTAL);  
  else
    DBMS_OUTPUT.PUT_LINE('No Data for this month');
  end if;   

END Proce_name;
/

这是一些测试代码 - http://sqlfiddle.com/#!4/b1068/2

【讨论】:

我已经完成了对 TO_char 的查询,但我需要检查传递给过程的日期。意思是如果 Monthly_date 存在然后显示结果。但是,如果日期不存在,则显示该月没有数据的消息。我不想使用 EXCEPTION,因为这是许多程序中的一个。所以我在同一日期有个别结果! 使用 EXCEPTION 只是更简洁的代码,但您不必真的这样做。您可以像以前那样使用 IF ELSE。尽管如此,还是没有办法避免 TO_CHAR。如果您需要 Pram_Date 为 DATE 类型,那没关系,只需将其作为日期传递并在您的选择中隐式转换。它看起来像这样 - CREATE OR REPLACE PROCEDURE Proce_Name (Pram_Date date) AS BEGIN ... SELECT ... WHERE to_char(monthly_date,'mm-yyyy') = to_char(Pram_Date,'mm-yyyy') ... 感谢您的回复。您能否根据您的评论更改代码? 完成。尽管小提琴已关闭,但无法对其进行测试。应该管用。如果是这样,将不胜感激:)

以上是关于使用 PL/SQL 的日期和条件的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL程序设计

PL/SQL oracle,使用日期和时间的测试窗口

PL/SQL:游标使用中的 ORA-01001

(十六)PL/SQL日期及时间

pl/sql 存储过程从日期等于存储过程参数的表中进行选择

PL/SQL 日期插入