简体   繁体   中英

Oracle Case statement not working

I'm trying to use the following case statement to extract information from my table, if I ignore the case statement and manually enter the day it works, but the case statement doesn't it just seems to jump directly to the else part, any suggestions please?

SELECT * FROM mytable WHERE day = CASE WHEN to_char(SYSDATE, 'DAY') = 'SATURDAY' THEN 'Sat'
                                       WHEN to_char(SYSDATE, 'DAY') = 'SUNDAY' THEN 'Sun'
                                       ELSE 'weekday' END;

For some reason the to_char function is padding the string with a space at the end, and it does not match. I tried this:

select '#' || to_char(SYSDATE+2, 'DAY') || '#' from dual 

and it returned: #SUNDAY #

Change your query to this:

SELECT * FROM mytable WHERE day = CASE WHEN trim(to_char(SYSDATE, 'DAY')) = 'SATURDAY' THEN 'Sat'
                                       WHEN trim(to_char(SYSDATE, 'DAY')) = 'SUNDAY' THEN 'Sun'
                                       ELSE 'weekday' END;

If you look at the documentation it states that for "DAY" - Name of day, padded with blanks to display width of the widest name of day in the date language used for this element.

Not what I expected.

There are two things to note:

  1. There is no need to TRIM the blank padding manually. Oracle provides FM ie Fill Mode format to get rid of the blank padding.

  2. You should mention the NLS_DATE_LANGUAGE explicitly since the format is NLS dependent .

From Oracle documentation on Format Model Modifiers :

FM

Fill mode. Oracle uses trailing blank characters and leading zeroes to fill format elements to a constant width. The width is equal to the display width of the largest element for the relevant format model:

  • Numeric elements are padded with leading zeros to the width of the maximum value allowed for the element. For example, the YYYY element is padded to four digits (the length of '9999'), HH24 to two digits (the length of '23'), and DDD to three digits (the length of '366').

  • The character elements MONTH, MON, DAY, and DY are padded with trailing blanks to the width of the longest full month name, the longest abbreviated month name, the longest full date name, or the longest abbreviated day name, respectively, among valid names determined by the values of NLS_DATE_LANGUAGE and NLS_CALENDAR parameters. For example, when NLS_DATE_LANGUAGE is AMERICAN and NLS_CALENDAR is GREGORIAN (the default), the largest element for MONTH is SEPTEMBER, so all values of the MONTH format element are padded to nine display characters. The values of the NLS_DATE_LANGUAGE and NLS_CALENDAR parameters are specified in the third argument to TO_CHAR and TO_* datetime functions or they are retrieved from the NLS environment of the current session.

  • The character element RM is padded with trailing blanks to the length of 4, which is the length of 'viii'.

  • Other character elements and spelled-out numbers (SP, SPTH, and THSP suffixes) are not padded.

The FM modifier suppresses the above padding in the return value of the TO_CHAR function.

So, you could use FMDAY instead of DAY format to get rid of the blank padding .

For example,

SQL> SELECT '#' || to_char(SYSDATE, 'fmDAY') || '#' as dt FROM dual;

DT
-----------
#SATURDAY#

SQL>

So, you could modify your case statement as:

SQL> SELECT
  2    CASE
  3      WHEN TO_CHAR(SYSDATE, 'FMDAY') = 'SATURDAY'
  4      THEN 'Sat'
  5      WHEN TO_CHAR(SYSDATE, 'FMDAY') = 'SUNDAY'
  6      THEN 'Sun'
  7      ELSE 'weekday'
  8    END as day
  9  FROM dual;

DAY
-------
Sat

SQL>

Use NLS_DATE_LANGUAGE

For example,

SQL> ALTER SESSION SET NLS_DATE_LANGUAGE='french';

Session altered.

SQL>
SQL> SELECT '#' || to_char(SYSDATE, 'fmDAY') || '#' as dt FROM dual;

DT
----------
#SAMEDI#

SQL>
SQL> ALTER SESSION SET NLS_DATE_LANGUAGE='english';

Session altered.

SQL>
SQL> SELECT '#' || to_char(SYSDATE, 'fmDAY') || '#' as dt FROM dual;

DT
-----------
#SATURDAY#

SQL>

So, you need to mention it at individual statement level:

SQL> SELECT
  2    CASE
  3      WHEN TO_CHAR(SYSDATE, 'FMDAY', 'NLS_DATE_LANGUAGE=ENGLISH') = 'SATURDAY'
  4      THEN 'Sat'
  5      WHEN TO_CHAR(SYSDATE, 'FMDAY', 'NLS_DATE_LANGUAGE=ENGLISH') = 'SUNDAY'
  6      THEN 'Sun'
  7      ELSE 'weekday'
  8    END AS DAY
  9  FROM dual;

DAY
-------
Sat

SQL>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM