2009-03-31 4 views
0

Je travaille actuellement sur un projet qui se comporte différemment selon qu'il s'agit d'un jour férié ou non (entre autres contraintes, évidemment). À cette fin, j'essaie de créer une table qui contient la date et le jour de la semaine (en considérant les vacances comme étant un huitième jour de la semaine).Oracle: Programme ne pas forcer correctement dans l'instruction SELECT CASE à une date

J'ai une table dont je suis la source de la liste des vacances, nommé holiday, qui a un seul champ, holidaydate (DATE type de données). La table dans laquelle j'essaie de mettre les valeurs est nommée daydates, avec deux champs, day (type de données DATE) et dayofweek (type de données CHAR(10)).

C'est la logique telle que je l'ai pour le moment, pendant que je teste.

INSERT INTO holiday 
    (holidaydate) 
SELECT sysdate FROM dual; 

SELECT sysdate, 
    (
    CASE 
    WHEN sysdate IN 
     (SELECT h.holidaydate FROM holiday h) 
    THEN 'holiday' 
    ELSE TO_CHAR(sysdate , 'day') 
    END) 
FROM dual; 

Malheureusement, il renvoie actuellement, disons, «mercredi», plutôt que «vacances». J'ai le sentiment que j'ai besoin de changer le WHEN sysdate IN en un WHEN to_char (sysdate, 'dd-mon-yyyy') IN ou quelque chose comme ça, mais j'ai essayé quelques variantes et ils ne semblent pas avoir fonctionné jusqu'à maintenant.

Des suggestions?

Répondre

5

Je pense que votre problème est qu'il atteindra presque jamais ce cas:

CASE 
    WHEN sysdate IN 
     (SELECT h.holidaydate FROM holiday h) 

Parce que, lorsque vous insérez SYSDATE dans la vacances tableau, il est insérée avec la date et informations de temps. Donc le cas que vous mentionnez n'est presque jamais exécuté. Essayez de ne comparer que les parties significatives de la date sur votre étui.

CASE 
    WHEN TRUNC(SYSDATE) IN (SELECT TRUNC(h.holidaydate) from holiday h) 

Cela devrait fonctionner.

+0

+1, mais je vous conseille d'utiliser Trunc (sysdate) au lieu de la conversion to_char.C'est un meilleur reflet de l'objectif du code, je pense. –

+0

Excellent conseil. Seriez-vous d'accord avec moi si je modifie ma réponse pour refléter votre suggestion? Merci! –

+0

il suffit de l'éditer, c'est une partie de l'idée de ce site. –

0

Vous avez demandé des suggestions ... donc

  • Avez-vous vérifié ce qui est inséré dans la table de vacances par la première déclaration, pour vous assurer qu'il est correct?
  • Avez-vous essayé de prendre sysdate hors de l'image (par exemple en utilisant une constante) pour voir si c'est ce qui cause le problème?
  • Avez-vous essayé de remplacer le sélecteur interne par une liste constante?
2

Dans votre table des fêtes, vous êtes uniquement intéressé par les dates et non par les composants horaires. Mettre une contrainte pour appliquer cela et arrêter toute personne qui fait la même erreur que vous avez fait:

CREATE TABLE HOLIDAY 
(holidaydate DATE NOT NULL 
       CONSTRAINT DateOnlyNoTime 
       CHECK (holidayDate = TRUNC(holidayDate))); 

Sans doute vous voulez une clé primaire et d'autres colonnes. La méthode préférée pour supprimer la partie date/heure d'une date est d'utiliser TRUNC() comme ci-dessus plutôt que TO_DATE() pour des raisons de performances. Votre exemple de requête deviendrait alors:

SELECT sysdate, 
    (
    CASE 
    WHEN TRUNC(sysdate) IN 
     (SELECT h.holidaydate FROM holiday h) 
    THEN 'holiday' 
    ELSE TO_CHAR(sysdate , 'day') 
    END) 
FROM dual; 
+0

+1, mais faites attention aux versions antérieures d'Oracle dans lesquelles l'optimiseur lit la contrainte et l'applique en tant que prédicat pouvant réduire de manière incorrecte la cardinalité attendue de l'ensemble de résultats. –

Questions connexes