变量比较不正确

时间:2018-10-26 16:09:58

标签: oracle date plsql toad

问题:为什么我的decode语句未返回我需要的值?

我注意到的第一件事是日期格式错误,因为Toad在DD/MM/RR中分配了日期,并且我试图将其与DD/MM/YYY进行比较。因此,我尝试在过程开始时设置nls格式。

请问如何解决这个问题?

请在下面找到代码

 declare

    vMES_ACTUAL                                         NUMBER(6);
    vMES_ANT                                            NUMBER(6);
    vTRIM_ANT                                           NUMBER(6);
    vTRIM_ACT                                           NUMBER(6);
    vMES_BASE                                           NUMBER(6);
    vMES_INTA                                           NUMBER(6);
    vMES_ULT_DIC                                        NUMBER(6);
    vFECHA                                              DATE;
    vMES_CURSO                                          NUMBER(6);
    ----------
    vFECHA1         DATE;
    vFECHA2         DATE;
    vFECHA3         DATE;
    vFECHA4         DATE;
    vFECHA5         DATE;
    vFECHA6         DATE;
    vNUM_DIAS_CARGA NUMBER;
    vSEMANAS_TRANSC NUMBER;
    var_mes1 number(6);
    var_mes2 number(6);
    var_mes3 number(6);
    ----------
    FEC_VAR_DIA      VARCHAR2(10);

    Pmes number(6):=201810;

    begin

    execute immediate 'alter session set nls_date_format = ''DD/MM/YYYY''';



       SELECT Pmes INTO vMES_CURSO FROM DUAL;

        /* Ultimos 6 dias de carga */

       SELECT MAX(ID_FECHA) INTO vFECHA1
        FROM CAP_BPP_FECHA_VAR6DIAS;

      SELECT NVL(MAX(ID_FECHA),vFECHA1) INTO vFECHA2
        FROM CAP_BPP_FECHA_VAR6DIAS
        WHERE ID_FECHA < vFECHA1;

      SELECT NVL(MAX(ID_FECHA),vFECHA2) INTO vFECHA3
       FROM CAP_BPP_FECHA_VAR6DIAS
       WHERE ID_FECHA < vFECHA2;

     SELECT NVL(MAX(ID_FECHA),vFECHA3) INTO vFECHA4
       FROM CAP_BPP_FECHA_VAR6DIAS
       WHERE ID_FECHA < vFECHA3;

   SELECT NVL(MAX(ID_FECHA),vFECHA4) INTO vFECHA5
     FROM CAP_BPP_FECHA_VAR6DIAS
    WHERE ID_FECHA < vFECHA4;

     SELECT NVL(MAX(ID_FECHA),vFECHA5) INTO vFECHA6
       FROM CAP_BPP_FECHA_VAR6DIAS
       WHERE ID_FECHA < vFECHA5;

      /* Hace el conteo de los numeros de dias */
     SELECT COUNT(*)
       INTO vNUM_DIAS_CARGA
     FROM CAP_BPP_FECHA_VAR6DIAS;


    EXECUTE IMMEDIATE ('TRUNCATE TABLE CAP_BPP_CTA_VAR_PASO');



 INSERT /*+  NOLOGGING */ INTO CAP_BPP_CTA_VAR6DIAS_PASO(
              ID_CLIENTE, ID_CONTRATO, ID_MES, ID_PRODUCTO, ID_SUBPRODUCTO, 
              ID_DIVISA,
              SDO_PUNT_DIA_1)
              SDO_PUNT_DIA_2,
              SDO_PUNT_DIA_3,
              SDO_PUNT_DIA_4,
              SDO_PUNT_DIA_5,
              SDO_PUNT_DIA_6)
    SELECT BT.ID_CLIENTE, BT.ID_CONTRATO, vMES_CURSO, BT.ID_PRODUCTO, 
    BT.ID_SUBPRODUCTO,BT.ID_DIVISA,
              CASE WHEN vNUM_DIAS_CARGA < 1 THEN 0 ELSE NVL(SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/YYYY'),vFECHA1,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_1
              CASE WHEN vNUM_DIAS_CARGA < 2 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA2,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_2,
              CASE WHEN vNUM_DIAS_CARGA < 3 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA3,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_3,
              CASE WHEN vNUM_DIAS_CARGA < 4 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA4,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_4,
              CASE WHEN vNUM_DIAS_CARGA < 5 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA5,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_5,
              CASE WHEN vNUM_DIAS_CARGA < 6 THEN 0 ELSE NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA6,SDO_PUNTUAL)),0) END SDO_PUNT_DIA_6
         FROM CAP_BPP_CTA_FTE_DIA BT
         WHERE BT.FECHA_INFORMACION IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)    
         GROUP BY ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO, ID_DIVISA;)

       COMMIT;



end;

2 个答案:

答案 0 :(得分:0)

您当前正在这样做:

NVL(SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/YYYY'),vFECHA1,SDO_PUNTUAL)),0)

评论中讨论的

不应将TO_DATE()应用于已经是日期的内容,因此您要么需要:

NVL(SUM(DECODE(BT.FECHA_INFORMACION,vFECHA1,SDO_PUNTUAL)),0)

在进行比较时,或者FECHA_INFORMACION具有除午夜以外的时间部分的值:

NVL(SUM(DECODE(TRUNC(BT.FECHA_INFORMACION),vFECHA1,SDO_PUNTUAL)),0)

TRUNC()函数默认将日期值的时间部分设置为午夜,因此一天中的所有值都将获得相同的datetime值。如果ID_FECHA也有非午夜时间,那么您也可以截断这些变量,尽管从联系人看来似乎不太像这样:

NVL(SUM(DECODE(TRUNC(BT.FECHA_INFORMACION),TRUNC(vFECHA1),SDO_PUNTUAL)),0)

您也可以在解码中将默认值设置为零,但是在这种情况下,应该没有太大的区别。


没有TO_DATE()及其隐式TO_CHAR()的NLS设置无关紧要,因为您正在将日期与其他日期进行比较。 Oracle使用内部表示形式,它与客户端如何将日期显示为字符串无关。


您可能对此也有疑问:

WHERE BT.FECHA_INFORMACION IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)

因为那也只能完全匹配午夜。您也可以截断它:

WHERE TRUNC(BT.FECHA_INFORMACION) IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)
再次

假设FECHA_INFORMACION具有非午夜时间,并且变量都位于午夜。这样可以防止使用FECHA_INFORMACION,但您可以改为比较多个范围。先看看能否解决问题。

答案 1 :(得分:0)

我以最简单的方式解决问题,也许我的问题的表达方式不正确,因为我只想匹配日期格式以从查询中获取数据。感谢那些试图帮助的人。这就是我解决的方法。

INSERT /*+  NOLOGGING */ INTO CAP_BPP_CTA_VAR6DIAS_PASO(
          ID_CLIENTE, ID_CONTRATO, ID_MES, ID_PRODUCTO, ID_SUBPRODUCTO, ID_DIVISA,
          SDO_PUNT_DIA_1,
          SDO_PUNT_DIA_2,
          SDO_PUNT_DIA_3,
          SDO_PUNT_DIA_4,
          SDO_PUNT_DIA_5,
          SDO_PUNT_DIA_6)
   SELECT /*+ PARALLEL(BT,4) */
          ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO,ID_DIVISA,
          CASE WHEN vNUM_DIAS_CARGA < 1 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA1,SDO_PUNTUAL)) END SDO_PUNT_DIA_1,
          CASE WHEN vNUM_DIAS_CARGA < 2 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA2,SDO_PUNTUAL)) END SDO_PUNT_DIA_2,
          CASE WHEN vNUM_DIAS_CARGA < 3 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA3,SDO_PUNTUAL)) END SDO_PUNT_DIA_3,
          CASE WHEN vNUM_DIAS_CARGA < 4 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA4,SDO_PUNTUAL)) END SDO_PUNT_DIA_4,
          CASE WHEN vNUM_DIAS_CARGA < 5 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA5,SDO_PUNTUAL)) END SDO_PUNT_DIA_5,
          CASE WHEN vNUM_DIAS_CARGA < 6 THEN 0 ELSE SUM(DECODE(TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR'),vFECHA6,SDO_PUNTUAL)) END SDO_PUNT_DIA_6
     FROM CAP_BPP_CTA_FTE_DIA BT
     WHERE TO_DATE(BT.FECHA_INFORMACION,'DD/MM/RR') IN (vFECHA1, vFECHA2, vFECHA3, vFECHA4, vFECHA5, vFECHA6)    
     GROUP BY ID_CLIENTE, ID_CONTRATO, vMES_CURSO, ID_PRODUCTO, BT.ID_SUBPRODUCTO, ID_DIVISA;

   COMMIT;