【问题标题】:SQL Developer - Using start and end date variables in where clause of my querySQL Developer - 在查询的 where 子句中使用开始和结束日期变量
【发布时间】:2010-11-03 01:38:47
【问题描述】:

我有一个每天运行的查询,它需要 StartDateEndDate 值。 StartDateEndDate 曾经是手动输入,但我试图摆脱它并计算要在查询中使用的 StartDateEndDate。我开发了代码来捕获变量中的StartDateEndDate

DECLARE

    c_DateMask VARCHAR2(20) := 'DD-Mon-YYYY';
    c_TimeMask VARCHAR2(20) := 'HH24:MI';

    v_Month char(4) := 'Prev'; 
    v_StartDate date; 
    v_EndDate date; 
    v_Environment char(7) := 'Prod';  

BEGIN

    if v_MONTH = 'Prev'
        THEN 
            select TO_DATE ('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy')) into v_StartDate from dual; 
            select Last_day(TO_DATE('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy'))) into v_EndDate from dual;
        ELSE
            select TO_DATE ('01-' || TO_CHAR (ADD_MONTHS (SYSDATE, 0),'mon-yyyy')) into v_StartDate from dual;
            CASE
                WHEN v_Environment = 'Prod'
                    THEN
                        -- Production Environment --
                          select 
                              to_char(sysdate, 'dd-Mon-yyyy ') ||
                              case 
                                  when to_char(sysdate, 'mi') between 00 and 20
                                    then to_char(sysdate, 'hh24')-1||':58'||':00' 
                                  when to_char(sysdate, 'mi') between 21 and 40
                                    then to_char(sysdate, ' hh24')||':18'||':00' 
                                  when to_char(sysdate, 'mi') between 41 and 60
                                    then to_char(sysdate, ' hh24')||':38'||':00'
                              END 
                          into v_EndDate from dual;
                WHEN v_Environment = 'OldTest'
                    THEN
                       -- Test Environment --
                            select 
                                to_char(sysdate, 'dd-Mon-yyyy ') ||
                                case 
                                when to_char(sysdate, 'mi') between 10 and 30
                                    then to_char(sysdate, 'hh24')||':08'||':00'
                                when to_char(sysdate, 'mi') between 31 and 50
                                    then to_char(sysdate, ' hh24')||':28'||':00' 
                                when to_char(sysdate, 'mi') between 51 and 60
                                    then to_char(sysdate, ' hh24')||':48'||':00'
                                END 
                            into v_EndDate from dual;
            end case;    
    end if;

然后我想在下面的 select 语句中使用变量:

    -----------------
    /* KPI Figures */
    -----------------

    SELECT 
        SysDate as RunTime
        , v_StartDate
        , v_EndDate
        , TTM_OFF_CONTRIBUTOR
        , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
    FROM  [Table]
    Where 
        TTM_PROCESSED_DATE    >= v_StartDate
        AND TTM_PROCESSED_DATE    <= v_EndDate
    group by SysDate, v_StartDate, v_EndDate, TTM_OFF_CONTRIBUTOR

END;

直到我尝试在 KPI 数字查询中使用变量值之前,这一切都有效。我错过了什么?

更新:

关于Phil's answer:我试过了,但没有成功,我收到以下错误:

PLS-00428: an INTO clause is expected in this SELECT statement.

我确定我昨天看到了另一个回复,该回复现在与能够为变量或其他东西分配多个值有关。

这是我需要的吗?我该怎么做?

【问题讨论】:

    标签: oracle variables oracle-sqldeveloper


    【解决方案1】:

    变量 v_StartDate 和 v_EndDate 仅在声明它们的 PL/SQL 块的范围内。看起来您正在尝试在单独的查询中在块之外使用它们。为此,您需要在 PL/SQL 块之外创建 SQL Developer 绑定变量,如下所示:

    var v_start_date varchar2(11)
    var v_end_date varchar2(11)
    

    然后在 PL/SQL 块和 SQL 查询中将它们作为绑定变量引用:

    declare
      ...
    begin
      ....
      :v_start_date := '01-' || TO_CHAR (ADD_MONTHS (SYSDATE, -1), 'mon-yyyy');
      :v_end_date := TO_CHAR(Last_day(TO_DATE('01-' 
                     || TO_CHAR (ADD_MONTHS (SYSDATE, -1),'mon-yyyy'))));
      -- (NB No need to select from dual)
      ...
    end;
    

    SQL:

    ...
    Where 
    TTM_PROCESSED_DATE    >= TO_DATE(:v_StartDate)
    AND TTM_PROCESSED_DATE    <= TO_DATE(:v_EndDate)
    

    请注意,这些变量不能用 DATE 类型声明,因此需要将它们转换回查询中的日期(使用正确的格式掩码)。

    【讨论】:

      【解决方案2】:

      我建议您将开始日期/结束日期包装在两个函数(存储过程)中

      create or replace function get_startdate(p_month in varchar2, p_env in varchar2)
      return date
      is
        l_return date;
      begin
         ... logic goes here ...
         return l_return;
      end;
      

      结束日期类似。

      然后在您的查询中使用这些函数:

      SELECT 
          SysDate as RunTime
          , get_startdate('Prev', 'Prod')
          , get_enddate('Prev', 'Prod')
          , TTM_OFF_CONTRIBUTOR
          , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
      FROM  [Table]
      Where 
          TTM_PROCESSED_DATE    >= get_startdate('Prev', 'Prod')
          AND TTM_PROCESSED_DATE    <= get_enddate('Prev', 'Prod')
      group by SysDate, get_startdate('Prev', 'Prod'), get_enddate('Prev', 'Prod'), TTM_OFF_CONTRIBUTOR
      

      旁注:请考虑使用更简洁的版本来确定一个月的第一天和最后一天。您也可以只为变量赋值而不使用 SELECT INTO,例如

      startdate := trunc(sysdate, 'MM'); -- first day of current month
      enddate := last_day(trunc(sysdate, 'MM')); -- last day of current month
      

      要以小时计算,您可以添加/减去分钟数,这比您所做的所有 to_date/to_char 转换更具可读性,例如

      enddate := trunc(sysdate, 'HH24');
      case 
        when to_char(sysdate, 'mi') between 00 and 20 then enddate := enddate - 2/(24*60);
        when to_char(sysdate, 'mi') between 21 and 40 then enddate := enddate + 18/(24*60);
        when to_char(sysdate, 'mi') between 41 and 60 then enddate := enddate + 38/(24*60);
      end; 
      

      祝你好运,马丁

      【讨论】:

        【解决方案3】:

        我认为问题在于您的查询和别名。试试

        SELECT 
            SysDate as RunTime
            , v_StartDate AS StartDate
            , v_EndDate AS EndDate
            , TTM_OFF_CONTRIBUTOR
            , SUM(NVL(TTM_PER_OFF_FEE,0)) Fees
        FROM  [Table]
        Where 
            TTM_PROCESSED_DATE    >= v_StartDate
            AND TTM_PROCESSED_DATE    <= v_EndDate
        group by RunTime, StartDate, EndDate, TTM_OFF_CONTRIBUTOR
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多