2010-07-22 13 views
0

Cela n'est probablement pas aussi compliqué que cela devrait l'être, mais Business Objects semble être très, très strict dans la façon dont les types sont utilisés par rapport à SQL Developer. Voici le morceau de la déclaration en question:Problème PL/SQL: pas un mois valide Erreur lors de la sélection via rapport d'objet métier

ship_date between '01' || '-' || w_current_ora_month || '-' || to_char(to_date(w_last_day, 'DD-MON-RR HH:MI:SS AM'), 'yy') and to_char(to_date(w_last_day, 'DD-MON-RR HH:MI:SS AM')) 

w_current_ora_month VARCHAR2 (3) est rempli par:

SELECT to_char(sysdate, 'MON') 
    INTO w_current_ora_month 
    FROM dual; 

w.last_day DATE est remplie via:

SELECT trunc(LAST_DAY('01' || '-' || w_current_ora_month || '-' || to_char(w_year))) 
    into w_last_day 
    from dual 

Pourquoi suis-je obtenir une erreur Mois non valide lors de l'extraction à partir de Business Objects? J'ai déjà trouvé que les objets Business sont très stricts sur les types, donc je me demande si je fais quelque chose de mal ici. Tout cela fonctionne très bien dans SQL Developer, mais j'ai dû modifier cette instruction encore et encore pour essayer de l'utiliser quand Business Objects l'utilise.

+0

La première moitié concatène les chaînes pour produire '01 -JUL-09 'tandis que la seconde moitié produit '31 -JUL-09' Le type de données est DATE. – jlrolin

Répondre

6

Vous comptez sur la conversion implicite des chaînes en dates, ce qui est toujours une mauvaise idée.

Si vous devez convertir en une chaîne puis revenir à une date, utilisez toujours to_date et un masque de date. Sinon, vous dépendez des variables NLS, qui peuvent être modifiées au cours d'une session (presque certainement la cause de votre problème).

Cependant, dans ce cas, vous n'êtes pas obligé de le faire. Votre condition peut être simplifiée:

ship_date between trunc(sysdate,'MON') and last_day(trunc(sysdate)) 

Comme @APC a souligné, si votre champ contient un composant de temps, vous aurez envie de tout jusqu'à la fin du dernier jour du mois. Ceci peut être réalisé de plusieurs façons:

ship_date between trunc(sysdate,'MON') 
       and last_day(trunc(sysdate))+(86399/86400) 

ship_date between trunc(sysdate,'MON') 
       and add_months(trunc(sysdate,'MON'),1)-(1/86400) 

ship_date >= trunc(sysdate,'MON') 
    and ship_date < add_months(trunc(sysdate,'MON'),1) 

J'ont tendance à préférer la dernière version qu'il va continuer à travailler si vous décidez de changer le champ à un TIMESTAMP sur la route.

+0

La solution de contournement proposée est certainement la meilleure façon de gérer ces choses. Notez que si SHIP_DATE inclut des enregistrements de composant de temps, la requête doit utiliser 'last_day (trunc (sysdate)) + (86399/86400)' – APC