Case, Decode or PlSQL

Hello,
I am new to Oracle. I have a, hopefully basic SQL question.
There is sometime four users in my dbs. But, I would like make query where the users below are returned, even if not in db.
1. Bob
2. Jane
3. John
4. Abul
I have rows in db:
ROWS IN DB
Username account status
bob Support Active
Jane Dev Active
John Dev Expired
How I can write query to find all users, if one is missing. Try to get format
Bob's Support account is active
Jane's Dev account is active
John's Dev account is active
Abul is not in db
I try CASE and Decode, but get bad returns.
Pls help.
Tring to learn SQL. Go to class in three weeks.

Hi,
Welcome to the forum!
So you have four special users, each with a name and id number. That sounds like data. Data belongs in tables. You should create a table that has four rows. Then you could use that table to do an outer-join with other tables, such as db.
If you don't have such a table, you can generate a result set on the fly that will serve as a table. The sub-query special_users below is just that:
WITH  special_users  AS
     SELECT  'Abul' AS username  FROM dual  UNION ALL
     SELECT     'BOB'                 FROM dual  UNION ALL
     SELECT     'Jane'                 FROM dual  UNION ALL
     SELECT     'John'                 FROM dual
SELECT     su.username
    ||  CASE
          WHEN  db.username IS NULL
          THEN  ' is not in db'
          ELSE  '''s ' || account
                          || ' account is '
                    || status
         END     AS msg
FROM     special_users     su
LEFT OUTER JOIN          db     ON     db.username     = su.username
;If you do have a real special_users table, then the main query above works;l just skip the WHERE clause (the forst 7 lines) and, the query is:
SELECT     su.username
    ||  CASE
          WHEN  db.username IS NULL
          THEN  ' is not in db'
          ELSE  '''s ' || account
                          || ' account is '
                    || status
         END     AS msg
FROM     special_users     su
LEFT OUTER JOIN          db     ON     db.username     = su.username
;Edited by: Frank Kulash on Sep 28, 2009 3:53 PM
The subject line you chose for this message, "Case, Decode or PlSQL" is very good, and shows the order in which you should try things.
(1) CASE is the general way to handle if-then-else logic in a SQL expression
(2) DECODE (and other specialized features, such as NVL2, which Michaels used) can save you a little typing in special circumstances. Once you have mastered CASE, you can start exploring these other expressions.
(3) PL/SQL is the last resort, used only if there is no good way to do something in SQL.

Similar Messages

  • CASE/DECODE in WHERE caluse

    Hi friends,
    Let's consider an EMP table has the following structure and data:
    create table EMP
    EMPNO NUMBER(4) not null,
    ENAME VARCHAR2(10),
    JOB VARCHAR2(9),
    MGR NUMBER(4),
    HIREDATE DATE,
    SAL NUMBER(7,2),
    COMM NUMBER(7,2),
    DEPTNO NUMBER(2),
    CONFDATE DATE
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7369, 'SMITH', 'CLERK', 7902, to_date('17-12-1980', 'dd-mm-yyyy'), 800, null, 20, to_date('27-12-1980', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7499, 'ALLEN', 'SALESMAN', 7698, to_date('20-02-1981', 'dd-mm-yyyy'), 1600, 300, 30, to_date('28-02-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7521, 'WARD', 'SALESMAN', 7698, to_date('22-02-1981', 'dd-mm-yyyy'), 1250, 500, 30, to_date('28-02-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7566, 'JONES', 'MANAGER', 7839, to_date('02-04-1981', 'dd-mm-yyyy'), 2975, null, 20, to_date('12-04-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7654, 'MARTIN', 'SALESMAN', 7698, null, 1250, 1400, 30, to_date('28-09-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7698, 'BLAKE', 'MANAGER', 7839, to_date('01-05-1981', 'dd-mm-yyyy'), 2850, null, 30, to_date('11-05-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7782, 'CLARK', 'MANAGER', 7839, to_date('09-06-1981', 'dd-mm-yyyy'), 2450, null, 10, to_date('19-06-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7788, 'SCOTT', 'ANALYST', 7566, null, 3000, null, 20, to_date('09-12-1982', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7839, 'KING', 'PRESIDENT', null, to_date('17-11-1981', 'dd-mm-yyyy'), 5000, null, 10, to_date('27-11-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7844, 'TURNER', 'SALESMAN', 7698, to_date('08-09-1981', 'dd-mm-yyyy'), 1500, 0, 30, to_date('18-09-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7876, 'ADAMS', 'CLERK', 7788, null, 1100, null, 20, to_date('12-01-1983', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7900, 'JAMES', 'CLERK', 7698, null, 950, null, 30, to_date('03-12-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7902, 'FORD', 'ANALYST', 7566, to_date('03-12-1981', 'dd-mm-yyyy'), 3000, null, 20, to_date('13-12-1981', 'dd-mm-yyyy'));
    insert into EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, CONFDATE)
    values (7934, 'MILLER', 'CLERK', 7782, to_date('23-03-1981', 'dd-mm-yyyy'), 1300, null, 10, to_date('31-05-1981', 'dd-mm-yyyy'));
    commit;
    Now I need to fetch the employees whose hire date is between 01-APR-1981 and 31-DEC-1981. If the hire date is null, then confirmation date has to be considered.
    For this input the following employees's records should be returned:
    7566
    7654
    7698
    7782
    7839
    7844
    7900
    7902
    I tried with CASE, DECODE in WHERE clause. But I couldn't succeed. Please help.
    Thanks in advance.
    Iniyavan

    SQL> ed
    Wrote file afiedt.buf
      1* select * from emp_test where nvl(hiredate,confdate)  between '01-APR-1981' and '31-DEC-1981'
    SQL> /
    EMP_TESTNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO CONFDATE
          7566 JONES      MANAGER         7839 02-APR-81       2975                    20 12-APR-81
          7654 MARTIN     SALESMAN        7698                 1250       1400         30 28-SEP-81
          7698 BLAKE      MANAGER         7839 01-MAY-81       2850                    30 11-MAY-81
          7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10 19-JUN-81
          7839 KING       PRESIDENT            17-NOV-81       5000                    10 27-NOV-81
          7844 TURNER     SALESMAN        7698 08-SEP-81       1500          0         30 18-SEP-81
          7900 JAMES      CLERK           7698                  950                    30 03-DEC-81
          7902 FORD       ANALYST         7566 03-DEC-81       3000                    20 13-DEC-81
    8 rows selected.@boopathi: Why to_char is needed here ? Further to_char(hire date,'DD_MON_YY') and comparing with '01-APR-1981' ? and WHAT is "_" doing in date format ? You sholud test your query before posting.
    Edited by: Saubhik on May 17, 2010 11:33 PM

  • Case/Decode

    Hello All,
    my table1 below
    FILE_ID    
    1
    2
    3Table2
    FILE_ID, FILE_NAME, P_FILE_ID
    11          pdp01             1
    12          pdp02              1
    13          pdp03              1I am trying something like this
    select    case WHEN d.file_name LIKE '%01%' THEN d.file_id
                  end 01_file_id_value,
            case WHEN d.file_name LIKE '%02%' THEN d.file_id
                  end 02_file_id_value
    from TABLE1 r , TABLE2 d
    where d.p_file_id = r.file_id'I am receiving something like
    01_file_id_value        02_file_id_value
    11                           
                                       12I need something like
    01_file_id_value        02_file_id_value
    11                              12I am not sure if we can do this with case/decode please help/guide me

    Hi,
    It looks like you want an aggregate query, something like this:
    select    MIN ( case
                         WHEN  d.file_name LIKE '%01%'  THEN d.file_id
                   end
               )        AS "01_file_id_value",                  -- non-standard alias must be in double-quotes
              MIN ( case
                        WHEN  d.file_name LIKE '%02%'  THEN d.file_id
                   end
               )        AS "02_file_id_value"                  -- non-standard alias must be in double-quotes
    from        TABLE1  r
    ,        TABLE2  d
    where        d.p_file_id = r.file_id
    ;What results would you want if there were two (or more) non-NULL values in the same column?
    Post a little sample data (CREATE TABLE and INSERT statements) for all tables, and also post the results you want from that data.
    Explain, using specific examples, how you get those results from that data.
    Always say which version of Oracle you're using.

  • No output for XML Publisher Report using CASE/DECODE in Where Clause

    Hi,
    I've a business requirement to modify an existing report which has two input parameters,
    -> p_statcode (Closed Status) which can have values 'Y' or 'N'
    -> p_overdue (Overdue Flag) which can have values 'Y' or 'N'
    The Overdue Flag is an evaluated column having values of Y/N and it is evaluated as follows,
    ONTF_MOD_VAL(NVL (
                                         (TRUNC (SYSDATE)
                                          - (TO_DATE (oe_order_lines.attribute18,
                                                      'DD-MON-RRRR')
                                             + TO_NUMBER (fnd_lookup_values.meaning))),
                                         0
                            overdue_flagThe user requirement now is they needs to be a third option for parameter p_overdue called ALL,
    passing which the output should include records having
    p_statcode is Y ELSE p_statcode is N AND p_overdue is Y OR p_overdue is N
    In other words records having both Y and N vlaues for Overdue Flag have to be returned irrespective of the value given to Closed Status.
    Original where clause in the Data Definition file is as follows,
    WHERE Closed_Status = nvl(:p_statcode,Closed_Status)
                       AND overdue_flag = nvl(:p_overdue,overdue_flag)My modified code is as follows,
    WHERE   Closed_Status = NVL (:p_statcode, Closed_Status)
             AND overdue_flag = (CASE
             WHEN :p_overdue = 'Y' THEN 'Y'
             WHEN :p_overdue = 'N' THEN 'N'
             ELSE overdue_flag
             END)
    OR
    WHERE   Closed_Status = NVL (:p_statcode, Closed_Status)
             AND overdue_flag = DECODE (:p_overdue, 'Y', 'Y', 'N', 'N',overdue_flag)Both approaches have the same problem.
    The output is in EXCEL format. The modified query works fine for p_overdue as Y or N but when p_overdue is passed as ALL it returns an empty EXCEL sheet with just the report output column headers.
    Any help as to why this is the case ?? What is wrong in my approach ?
    Regards,
    Vishal

    not clear about p_overdue = ALL
    which values needed for p_overdue = ALL ?
    try smth like
    WHERE   Closed_Status = NVL (:p_statcode, Closed_Status)
    AND (
       overdue_flag = DECODE (:p_overdue, 'Y', 'Y', 'N', 'N',overdue_flag) and :p_overdue != 'ALL'
       or
      :p_overdue = 'ALL' and (overdue_flag = 'Y' or overdue_flag = 'N')
    )for overdue_flag which has more then 'Y', 'N' values
    if overdue_flag only in ('Y','N') then
    WHERE   Closed_Status = NVL (:p_statcode, Closed_Status)
    AND (
       overdue_flag = DECODE (:p_overdue, 'Y', 'Y', 'N', 'N',overdue_flag) and :p_overdue != 'ALL'
       or
      :p_overdue = 'ALL'
    )

  • Case Decode - invalid column name error

    select Workweek, max( decode( Type, T34, prct, null ) ) Bad,
                        max( decode( Type, T35, prct, null ) ) Repair,
                        max( decode( Type, T36, prct, null ) ) Good
    FROM
    (select Workweek, Type, round(ratio_to_report(sum(Testtime_in_Minutes)) over(partition by Workweek)*100,3) prct
    FROM
    (select ts.lot as Lot, ts.wafer_id as Wafer, dt.SORT_X as X, dt.SORT_Y as Y, ts.devrevstep as PRODUCT, ts.operation as OPERATION, dt.INTERFACE_BIN as INTERFACE_BIN, (dt.TEST_TIME)/60.0 as Testtime_in_Minutes,
    ts.TEST_END_DATE_TIME as Test_End_Time, ts.Program_Name, ts.test_end_work_week as Workweek,
    (CASE
    WHEN (dt.INTERFACE_BIN > 9 AND dt.INTERFACE_BIN < 15) THEN 'T34'
    WHEN (dt.INTERFACE_BIN =30 OR dt.INTERFACE_BIN =31 OR dt.INTERFACE_BIN = 32 OR dt.INTERFACE_BIN = 33) THEN 'T35'
         ELSE 'T36'
         END ) Type
    from a_testing_session ts, a_device_testing dt
    where ts.test_end_work_week >= 200715
    and (ts.devrevstep like '9600%')
    and dt.lao_start_ww = ts.test_end_work_week
    and dt.ts_id = ts.ts_id)
    GROUP BY Workweek, Type)
    This sql query above does not run properly, gives invalid column name error. However, the entire select statement surrounded by the () works. There must be an error in the first 4 lines someplace, but I do not see it.

    Assuming type is a string, I assume you meant
    MAX( DECODE( type, 'T34', prct, NULL )) Badwhere T34 is a string literal. Otherwise, you'd need to have columns named T34, T35, and T36 in your inner select.
    One note, though, it's probably a bad idea to have a column named Type. While it's legal to do so, TYPE is a keyword in SQL, so that name will at a minimum be confusing.
    Justin

  • Owb 9 Case / decode statement

    Hi all,
    We using owb 9. Case staments can not be used in this version of owb. Could be done with a decode statement.
    But decode statements requires a static value to result a value.
    In my statement i want to use less the or greater the staments. How can i do that  in a decode.
    I found out a decode does also not work. anyone a idea. except for using a view as source
    so a example what i want:
    a < 180 then 1
    a between 180 and 200 then 2
    a > 200 then 3
    tnx in advanced
    Edited by: user565199 on 22-jun-2011 3:59

    Hi ,
    Did you try with case statement, if you try with case what error your getting?
    Thanks,
    Praveen

  • Update statement that includes case, decode and from clause

    hello
    I've the following code. I ran this code in 9i and got the errror SQL command not properly ended. Can I use FROM clause in an update statement?
    CREATE OR REPLACE procedure NRI
    IS
    BEGIN
    UPDATE IEB2 SET SDI =
    (CASE PSDI WHEN '11' THEN '16'
    WHEN '13' THEN '38'
    WHEN '14' THEN '18'
    WHEN '23' THEN '21'
    WHEN '24' THEN '21'
    WHEN '31' THEN '27'
    WHEN '32' THEN '37'
    WHEN '33' THEN '38'
    WHEN '34' THEN '37'
    WHEN '43' THEN '46'
    WHEN '53' THEN '45'
    WHEN '55' THEN '48'
    WHEN '60' THEN '54'
    WHEN '61' THEN '57'
    WHEN '62' THEN '54'
    WHEN '63' THEN '56'
    WHEN '64' THEN '52'
    WHEN '70' THEN '21'
    WHEN '77' THEN '25'
    WHEN '78' THEN '41'
    WHEN '80' THEN '79'
    WHEN '85' THEN '75'
    WHEN '87' THEN '73'
    WHEN '15' THEN '15'
    WHEN '51' THEN '51'
    WHEN '88' THEN '88'
    WHEN '00' THEN '00'
    WHEN '99' THEN '99'
    WHEN '12' THEN DECODE(C.R_ID, 'N', '16','18')
    ELSE 'NONE' END)
    FROM D1.C C
    WHERE EXISTS
    (SELECT 1
    FROM D1.SD A, D2.SDP B, D1.C C
    WHERE A.SDN = B.DN
    AND B.SDI = '000000'
    AND B.PFI = 'W'
    AND B.CID = C.CID
    AND A.SDN = '0001500721');
    END;

    Your parenthesis look a tad messed up ... think this fixes them.
    CREATE OR REPLACE procedure NRI
    IS
    BEGIN
    UPDATE IEB2 SET SDI =
    SELECT
    CASE PSDI
      WHEN '11' THEN '16'
      WHEN '13' THEN '38'
      WHEN '14' THEN '18'
      WHEN '23' THEN '21'
      WHEN '24' THEN '21'
      WHEN '31' THEN '27'
      WHEN '32' THEN '37'
      WHEN '33' THEN '38'
      WHEN '34' THEN '37'
      WHEN '43' THEN '46'
      WHEN '53' THEN '45'
      WHEN '55' THEN '48'
      WHEN '60' THEN '54'
      WHEN '61' THEN '57'
      WHEN '62' THEN '54'
      WHEN '63' THEN '56'
      WHEN '64' THEN '52'
      WHEN '70' THEN '21'
      WHEN '77' THEN '25'
      WHEN '78' THEN '41'
      WHEN '80' THEN '79'
      WHEN '85' THEN '75'
      WHEN '87' THEN '73'
      WHEN '15' THEN '15'
      WHEN '51' THEN '51'
      WHEN '88' THEN '88'
      WHEN '00' THEN '00'
      WHEN '99' THEN '99'
      WHEN '12' THEN DECODE(C.R_ID, 'N', '16','18')
      ELSE 'NONE'
    END
    FROM D1.C C
    WHERE EXISTS 
        SELECT 1
        FROM D1.SD A, D2.SDP B, D1.C C
        WHERE A.SDN = B.DN
        AND B.SDI = '000000'
        AND B.PFI = 'W'
        AND B.CID = C.CID
        AND A.SDN = '0001500721'
    END;

  • SELECTing records from two tables. Set Operators, CASE, DECODE, ...

    Hi all,
    I have two tables:
    CRETE TABLE T1 (T1_COL1 NUMBER, T1_COL2 NUMBER)
    CRETE TABLE T2 (T2_COL1 NUMBER, T2_COL2 NUMBER)
    T1 may or may not have records. T2 always has records. There are two scenarios.
    Scenario 1:
    =======
    SELECT * FROM T1 returns five rows, and SELECT * FROM T2 returns 10 rows.
    Now I need the five rows from T1.
    Scenario 2:
    =======
    SELECT * FROM T1 returns zero rows, and SELECT * FROM T2 returns 10 rows.
    Now I need the 10 rows from T2.
    In other words, if records present in T1, I need them all. If not, I need records from T2.
    There are no common columns (for joins).
    Now need a single query to achive this. I tried set operators, CASE and DECODE. But I'm unable to solve it.
    Please help. Thanks in advance.

    Iniyavan wrote:
    Yes, Justin. I'm sure that this is the way it's modelled. I also find it's tough and odd.Are you sure it's the right way for that data to be modeled? I understand that's the way it is being modeled, but a data model change may be the best option.
    Is there any other way, which is simpler, without using RANK?That's the simplest option I can think of. You could also do something like
    SELECT t1_col1, t1_col2
      FROM (
        SELECT t1_col1, t1_col2, rownum rn
          FROM (
            SELECT t1_col1, t1_col2
              FROM (
                SELECT t1_col1, t1_col2, 1 tbl
                  FROM t1
                UNION ALL
                SELECT t2_col2, t2_col2, 2 tbl
                  FROM t2       
             ORDER BY tbl
    WHERE rn = 1I'm not sure that's any simpler...
    Justin

  • Unable to return a number from CASE statement in plsql

    Hello all!
    Back in November of last year, I received some assistance from user "jarola" regarding changing the color of a column item in a query based on the resulting value. This discussion yielded;
    declare
       l_query varchar2(4000) := '';
    begin
       l_query := '
         select i.INVENTORY_ID,
                io.ORDER_QUANTITY,
                CASE
                   WHEN i.QUANTITY_AVAILABLE=0
                   THEN ''<span style="color:red;"> ''|| i.QUANTITY_AVAILABLE ||''</span>''
                   ELSE to_char(i.QUANTITY_AVAILABLE)
                END,
                i.QUANTITY_AVAILABLE qty_avail_hold,
                i.STRAIN_CODE,
                i.STRAIN_NAME,
                i.GENOTYPE,
                i.AGE,
                i.***,
                (lower(substr(i.ROOM_NUMBER,1,instr(i.ROOM_NUMBER,''-'',1,1)-1))) ROOM_NUMBER
         from   SM_INVENTORY i,
                SM_INVENTORY_ORDER io
         where  io.ORDER_ID (+)= :F111_MODIFYING_ORDER
         and    io.INVENTORY_ID (+)= i.INVENTORY_ID';
    return l_query;
    end;Problem is, sorting (report attributes for column set to "sort") on column i.QUANTITY_AVAILABLE is broken as even though the data in the table is number(12,0), the CASE statement returns it as alpha. I'm having difficulty getting this CASE statement to return a number as these modifications cause generic compilation errors.
    ELSE i.QUANTITY_AVAILABLE
    ELSE to_number(i.QUANTITY_AVAILABLE)
    Google/sqlplus docs have yielded little. Might anyone offer advice?
    Thanks!!!
    Paul

    Hello Varad! Thanks for the reply.
    Sorry, but I copied some old information in my code example. the CASE statement I'm actually using is;
    CASE
       WHEN i.QUANTITY_AVAILABLE=0
       THEN ''<span style="color:red;"> ''|| i.QUANTITY_AVAILABLE ||''</span>''
       ELSE to_char(i.QUANTITY_AVAILABLE)
       END AS QUANTITY_AVAILABLESo I'm already returning the result as labeled "QUANTITY_AVAILABLE".
    What I did was click on the pencil/paper icon to the left of the alias of my column in the "Column Attributes" pane in "Report Attributes" to get to the "Column Attributes" page and plugged #QUANTITY_AVAILABLE# into the HTML Expression field of the "Column Formatting" pane of the "Column Attributes" page for the "QUANTITY_AVAILABLE" column.
    No joy, sort still broken...
    Isn't the problem that fundamentally, the CASE statement returns an alpha? I wouldn't expect the sort to ever work until it can return a number (which it appears SQL, used this way, it cannot do).
    So, I considered that END AS QUANTITY_AVAILABLE might be the problem as it's named the same as the column, so I changed it (and the HTML Expression entry) to END AS QUANTITY_AVAIL (changed the name).
    Sort as alpha still happening.
    Any other thoughts?

  • Case, decode functions

    Dear All,
    Im having the table like
    the following,
    i need ther report like if i give role ,region and segment mean then i need onmenuid 2 alone.
    if input is role and region alone the i need those combinations result alone .
    if the input is role alone thatn i need that combinations menu id.
    MENUID     ROLE     REGION      SEGMENT
    13               
    27     Account Manager          
    29     Account Manager          
    1     Account Manager          
    2     Account Manager SOUTH     
    2     COO     EAST      Corporate
    Thanks In Advance,
    839083

    You posted in wrong forum.
    Please post at PL/SQL
    Hope this helps..
    If someone's response is helpful or correct, please mark it accordingly.

  • CASE STATEMENTS AND CASE EXPRESSIONS IN ORACLE9I PL/SQL

    제품 : PL/SQL
    작성날짜 : 2001-11-13
    CASE STATEMENTS AND CASE EXPRESSIONS IN ORACLE9I PL/SQL
    =======================================================
    PURPOSE
    아래의 자료는 Case 문에서 oracle 8.1.7과 Oracle 9i의 New Feature로 8.1.7에서는
    sqlplus 에서만 가능했고, 9i 부터는 pl/sql 까지 가능하다.
    Explanation
    1. Oracle 8.1.7 Feature
    Oracle 8.1.7 에서 Case 문은 Decode 문과 유사하지만, 기존의 decode 문을 쓰는 것보다
    더 많은 확장성과 Logical Power와 좋은 성능을 제공한다. 주로 나이와 같이 category 별로
    나눌때 주로 사용하고 Syntex는 아래와 같다.
    CASE WHEN <cond1> THEN <v1> WHEN <cond2> THEN <v2> ... [ELSE <vn+1> ] END
    각각의 WHEN...THEN 절의 argument 는 255 까지 가능하고 이 Limit를 해결하려면
    Oracle 8i Reference를 참조하면 된다.
    The maximum number of arguments in a CASE expression is 255, and each
    WHEN ... THEN pair counts as two arguments. To avoid exceeding the limit of 128 choices,
    you can nest CASE expressions. That is expr1 can itself be a CASE expression.
    Case Example : 한 회사의 모든 종업원의 평균 봉급을 계산하는데 봉급이 $2000보다 작은경우
    2000으로 계산을 하는 방법이 pl/sql을 대신하여 case function을 사용할 수 있다.
    SELECT AVG(CASE when e.sal > 2000 THEN e.sal ELSE 2000 end) FROM emp e;
    Case Example : 나이를 column으로 가지고 있는 customer table을 예로 들어보자.
    SQL> SELECT
    2 SUM(CASE WHEN age BETWEEN 70 AND 79 THEN 1 ELSE 0 END) as "70-79",
    3 SUM(CASE WHEN age BETWEEN 80 AND 89 THEN 1 ELSE 0 END) as "80-89",
    4 SUM(CASE WHEN age BETWEEN 90 AND 99 THEN 1 ELSE 0 END) as "90-99",
    5 SUM(CASE WHEN age > 99 THEN 1 ELSE 0 END) as "100+"
    6 FROM customer;
    70-79 80-89 90-99 100+
    4 2 3 1
    1 SELECT
    2 (CASE WHEN age BETWEEN 70 AND 79 THEN '70-79'
    3 WHEN age BETWEEN 80 and 89 THEN '80-89'
    4 WHEN age BETWEEN 90 and 99 THEN '90-99'
    5 WHEN age > 99 THEN '100+' END) as age_group,
    6 COUNT(*) as age_count
    7 FROM customer
    8 GROUP BY
    9 (CASE WHEN age BETWEEN 70 AND 79 THEN '70-79'
    10 WHEN age BETWEEN 80 and 89 THEN '80-89'
    11 WHEN age BETWEEN 90 and 99 THEN '90-99'
    12* WHEN age > 99 THEN '100+' END)
    SQL> /
    AGE_G AGE_COUNT
    100+ 1
    70-79 4
    80-89 2
    90-99 3
    Example
    2. Oracle 9i Feature
    Oracle 9i부터는 pl/sql에서도 case문을 사용할 수 있으면 이것은
    복잡한 if-else 구문을 없애고, C언어의 switch문과 같은 기능을 한다.
    아래의 9i pl/sql Sample 및 제약 사항을 보면 아래와 같다.
    Sample 1:
    A simple example demonstrating the proper syntax for a case
    statement
    using a character variable as the selector. See the section entitled
    'Restrictions' at the end of this article for details on which PLSQL
    datatypes may appear as a selector in a case statement or
    expression.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    declare
    achar char(1) := '&achar';
    begin
    case achar
    when 'A' then dbms_output.put_line('The description was Excellent');
    when 'B' then dbms_output.put_line('The description was Very Good');
    when 'C' then dbms_output.put_line('The description was Good');
    when 'D' then dbms_output.put_line('The description was Fair');
    when 'F' then dbms_output.put_line('The description was Poor');
    else dbms_output.put_line('The description was No such Grade');
    end case;
    end;
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    Sample 2:
    A simple example demonstrating the proper syntax for a case
    expression
    using a character variable as the selector. See the section entitled
    'Restrictions' at the end of this article for details on which PLSQL
    datatypes may appear as a selector in a case statement or
    expression.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    declare
    achar char(1) := '&achar';
    description varchar2(20);
    begin
    description :=
    case achar
    when 'A' then 'Excellent'
    when 'B' then 'Very Good'
    when 'C' then 'Good'
    when 'D' then 'Fair'
    when 'F' then 'Poor'
    else 'No such grade'
    end;
    dbms_output.put_line('The description was ' || description);
    end;
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    NOTE: The above simple samples demonstrate two subtle differences in the
    syntax
    required for case statements and expressions.
    1) A case STATEMENT is terminated using the 'end case' keywords; a
    case
    EXPRESSION is terminated using only the 'end' keyword.
    2) Each item in a case STATEMENT consists of one or more
    statements, each
    terminated by a semicolon. Each item in a case expression
    consists of
    exactly one expression, not terminated by a semicolon.
    Sample 3:
    Sample 1 demonstrates a simple case statement in which the selector
    is
    compared for equality with each item in the case statement body.
    PL/SQL
    also provides a 'searched' case statement as an alternative; rather
    than
    providing a selector and a list of values, each item in the body of
    the
    case statement provides its own predicate. This predicate can be any
    valid boolean expression, but only one case will be selected.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    declare
    achar char(1) := '&achar';
    begin
    case
    when achar = 'A' then dbms_output.put_line('The description was
    Excellent');
    when achar = 'B' then dbms_output.put_line('The description was Very
    Good');
    when achar = 'C' then dbms_output.put_line('The description was
    Good');
    when achar = 'D' then dbms_output.put_line('The description was
    Fair');
    when achar = 'F' then dbms_output.put_line('The description was
    Poor');
    else dbms_output.put_line('The description was No such Grade');
    end case;
    end;
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    Sample 4:
    This sample demonstrates the proper syntax for a case expression of
    the
    type discussed in Sample 3 above.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    declare
    achar char(1) := '&achar';
    description varchar2(20);
    begin
    description :=
    case
    when achar = 'A' then 'Excellent'
    when achar = 'B' then 'Very Good'
    when achar = 'C' then 'Good'
    when achar = 'D' then 'Fair'
    when achar = 'F' then 'Poor'
    else 'No such grade'
    end;
    dbms_output.put_line('The description was ' || description);
    end;
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    Sample 5:
    This sample demonstrates the use of nested case statements. It is
    also
    permissable to nest case expressions within a case statement (though
    it
    is not demonstrated here), but nesting of case statements within a
    case
    expression is not possible since statements do not return any value.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    declare
    anum1 number := &anum1;
    anum2 number := &anum2;
    answer number;
    begin
    case anum1
    when 1 then case anum2
    when 1 then answer := 10;
    when 2 then answer := 20;
    when 3 then answer := 30;
    else answer := 999;
    end case;
    when 2 then case anum2
    when 1 then answer := 15;
    when 2 then answer := 25;
    when 3 then answer := 35;
    else answer := 777;
    end case;
    else answer := 555;
    end case;
    dbms_output.put_line('The answer is ' || answer);
    end;
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    Sample 6:
    This sample demonstrates nesting of case expressions within another
    case
    expression. Note again the absence of semicolons to terminate both
    the
    nested case expression and the individual cases of those
    expressions.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    declare
    anum1 number := &anum1;
    anum2 number := &anum2;
    answer number;
    begin
    answer :=
    case anum1
    when 1 then case anum2
    when 1 then 10
    when 2 then 20
    when 3 then 30
    else 999
    end
    when 2 then case anum2
    when 1 then 15
    when 2 then 25
    when 3 then 35
    else 777
    end
    else 555
    end;
    dbms_output.put_line('The answer is ' || answer);
    end;
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    Although PL/SQL anonymous blocks have been used in all of the examples
    so far,
    case statements and expressions can also be used in procedures,
    functions, and
    packages with no changes to the syntax.
    The following samples are included for completeness and demonstrate the
    use of
    case statements and/or expressions in each of these scenarios.
    Sample 7:
    This sample demonstrates use of a case statement in a stored
    procedure.
    Note that this sample also demonstrates that it is possible for each
    of
    the items in the case body to consist of more than one statement.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    create or replace procedure testcasestmt ( anum IN number ) is
    begin
    case
    when anum = 1 then dbms_output.put_line('The number was One');
    dbms_output.put_line('In case 1');
    when anum = 2 then dbms_output.put_line('The number was Two');
    dbms_output.put_line('In case 2');
    when anum = 3 then dbms_output.put_line('The number was Three');
    dbms_output.put_line('In case 3');
    when anum = 4 then dbms_output.put_line('The number was Four');
    dbms_output.put_line('In case 4');
    when anum = 5 then dbms_output.put_line('The number was Five');
    dbms_output.put_line('In case 5');
    else dbms_output.put_line('The description was Invalid input');
    dbms_output.put_line('In the else case');
    end case;
    end;
    exec testcasestmt(&anum);
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    Sample 8:
    This sample demonstrates the use of a case statement in a stored
    package.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    create or replace package testpkg2 is
    procedure testcasestmt ( anum IN number );
    function testcasestmt_f ( anum IN number ) return number;
    end testpkg2;
    create or replace package body testpkg2 is
    procedure testcasestmt ( anum IN number ) is
    begin
    case
    when anum = 1 then dbms_output.put_line('The number was One');
    dbms_output.put_line('In case 1');
    when anum = 2 then dbms_output.put_line('The number was Two');
    dbms_output.put_line('In case 2');
    when anum = 3 then dbms_output.put_line('The number was Three');
    dbms_output.put_line('In case 3');
    when anum = 4 then dbms_output.put_line('The number was Four');
    dbms_output.put_line('In case 4');
    when anum = 5 then dbms_output.put_line('The number was Five');
    dbms_output.put_line('In case 5');
    else dbms_output.put_line('The description was Invalid input');
    dbms_output.put_line('In the else case');
    end case;
    end;
    function testcasestmt_f ( anum IN number ) return number is
    begin
    case
    when anum = 1 then dbms_output.put_line('The number was One');
    dbms_output.put_line('In case 1');
    when anum = 2 then dbms_output.put_line('The number was Two');
    dbms_output.put_line('In case 2');
    when anum = 3 then dbms_output.put_line('The number was Three');
    dbms_output.put_line('In case 3');
    when anum = 4 then dbms_output.put_line('The number was Four');
    dbms_output.put_line('In case 4');
    when anum = 5 then dbms_output.put_line('The number was Five');
    dbms_output.put_line('In case 5');
    else dbms_output.put_line('The description was Invalid input');
    dbms_output.put_line('In the else case');
    end case;
    return anum;
    end;
    end testpkg2;
    exec testpkg2.testcasestmt(&anum);
    variable numout number
    exec :numout := testpkg2.testcasestmt_f(&anum);
    print numout
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    Sample 9:
    This sample demonstrates the use of a case expression in a stored
    package.
    - - - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - -
    set serveroutput on
    create or replace package testpkg is
    procedure testcase ( anum IN number );
    function testcase_f ( anum IN number ) return number;
    end testpkg;
    create or replace package body testpkg is
    procedure testcase ( anum IN number ) is
    anumber number := anum;
    anothernum number;
    begin
    anothernum :=
    case
    when anumber = 1 then anumber + 1
    when anumber = 2 then anumber + 2
    when anumber = 3 then anumber + 3
    when anumber = 4 then anumber + 4
    when anumber = 5 then anumber + 5
    else 999
    end;
    dbms_output.put_line('The number was ' || anothernum);
    end;
    function testcase_f ( anum IN number ) return number is
    anumber number := anum;
    anothernum number;
    begin
    anothernum :=
    case
    when anumber = 1 then anumber + 1
    when anumber = 2 then anumber + 2
    when anumber = 3 then anumber + 3
    when anumber = 4 then anumber + 4
    when anumber = 5 then anumber + 5
    else 999
    end;
    dbms_output.put_line('The number was ' || anothernum);
    return anothernum;
    end;
    end testpkg;
    variable numout number
    exec testpkg.testcase(&anum);
    exec :numout := testpkg.testcase_f(&anum);
    print numout
    - - - - - - - - - - - - - - - - Code ends here - - - - - - - - - - - -
    제약 사항
    다음의 databasetype은 case 문에서 지원되지 않는다.
    BLOB
    BFILE
    VARRAY
    Nested Table
    PL/SQL Record
    PL/SQL Version 2 tables (index by tables)
    Object type (user-defined type)
    All of these types except for object types face a similar restriction
    even for if statements (i.e. they cannot be compared for equality directly) so this is unlikely to change for these types. Lack of support for object types is simply an implementation restriction which may be relaxed in future releases.
    Reference Ducumment
    Oracle 8.1.7 Manual
    NOTE:131557.1

    I have done the following code but doesn't
    like the statement of - "case(butNext)". What do you mean "doesn't like" -- did you get an error message?
    I'm guessing it won't compile because you're trying to switch on a Button.
    I tried something
    like "g.fillOval(100,50,70,90, BorderLayout.NORTH)"...no that doesn't make sense. You only use BorderLayout.NORTH when you're adding components to a BorderLayout layout manager. An oval is not a component and fillOval isn't adding a component and Graphics is not a Panel or layout manager.
    Would appreciate it if someone could tell me how to position
    shapes using the graohic method. I think the problem is that you're confusing shapes with components.

  • In Line CASE Statement OR Function

    Hi Gurus,
    What approach do you typically take in queries where you need to run CASE/DECODE type logic on a query? Obviously for small logic sets DECODE or CASE is fine in the query, but when I have to run a lot of logic for a column output I tend to prefer the FUNCTION. The problem with that approach is the performance. I have read about Function Based Indexes, but they seem to be more for FUNCTIONS that would go against a Single table (i.e. UPPER(CustomerName)).
    I would greatly appreciate any info/comments about how to approach this. What I am finding is that in my initial phases of a project my current query(s) are fine, but then as time passes more and more logic needs to be applied and my CASE/DECODES become very hard to maintain.
    Thanks,
    S

    You are correct they are user defined functions. I will take a look at the link you provided....thanks for the info.
    Your statement about he data model is what is basiclaly the problem. I have to look at all kind of identifiers, values to determine things like Shipping Rates, Pricing, Qty, etc. What started out as not being that bad has turned into a real headache to try and maintain the logic.
    I was trying to implement some user defined FUNCTIONs to break the logic out of the base queries thinking that would help make the code more maintainable, but have started to encounter some performance issues.
    --S                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   

  • Decoding- best way to decode characters to numbers using a conversion table

    I have input string which mostly contains numbers, but at the end there are 2 characters which means a country code, like 'EE' for estonia, or 'LV' for latvia and so on, see example input value:
    select '9999123456789012EE00' input, null output from dual;I want into column Output to put value where those 2 characters are decoded/replaced with numbers with following algorithm:
    1. replace in input string 9999123456789012EE00 characters with numbers 14 and 14 so the output would be 9999123456789012141400.
    2. The 14 was for specially letter 'E', all alphabet is encoded like following:
    A=10
    B=11
    C=12
    D=13
    E=14
    Y=34
    Z=35
    So, value "9999123456789012LV00" should be converted into 9999123456789012213100 (L = 21, V =31).
    What is the best way to achieve such decoding in plsql/sql?
    Edited by: CharlesRoos on Mar 16, 2010 3:52 AM

    Thx, Seems very nice.
    with t as (
      select '9999123456789012LV00' input from dual 
      union all
      select '9999123456789012AA00' input from dual
      union all
      select '9AA99912345678901200' input from dual
    select input,
           regexp_replace (input,  '[[:alpha:]]+',
                           (ascii (regexp_substr (input, '[[:alpha:]]')) - 55) || (ascii (regexp_substr (input, '[[:alpha:]]',1,2)) - 55))output
    from t
    9999123456789012LV00     9999123456789012213100
    9999123456789012AA00     9999123456789012101000
    9AA99912345678901200     9101099912345678901200
    ;

  • Problem with OWB Paris (case expression)

    I've got a little problem with defining an attribute property. I've defined a simple case statement: case when LKP_IN.TEST_TAB_ID is null then 'INS' else 'UPD' end. When I validate the expression I get the following error message:
    Line 1, Col 8:
    PLS-00103: Encountered the symbol "when" when expecting one of the following:
    . ( * @ % & = - + ; < / > at in is mod remainder not rem
    <an exponent (**)> <> or != or ~= >= <= <> and or like LIKE2_
    LIKE4_ LIKEC_ between || multiset member SUBMULTISET_
    The symbol ". was inserted before "when" to continue.
    Line 1, Col 50:
    PLS-00103: Encountered the symbol "THEN" when expecting one of the following:
    ; and or
    Needless to say that this worked well with OWB 10g R1. Any clue?
    Thanks in advance
    Jörg

    Hello, Jörg
    To what database are you trying to deploy your mapping? It seems that db version is pre-9i?
    If so, note that CASE statement is unavailable in PL/SQL until Oracle 9i – it’s available only in SQL (in pre-9i Oracle had different code from SQL and PL/SQL interpretation, after 9i it share interpreter code). The compilation error may appear in “ROW-based” parts of package: OWB generates code that calls CASE statement directly in PL/SQL – it cause error.
    To avoid deployment error “wrap” this expression component by some operator (order, dedup, join, set). In this case OWB pack expression along with “wrap” operator in SQL statement and package will compile.
    Where were discussion here (in forum) about using analytical function in mapping – the same approach works for CASE / DECODE if deploying to pre-9i database.
    Sergey

  • Difference between Oracle 8i and 9i

    Hi,
    Can anyone suggest me what's the difference ( in sql and pl/sql) between Oracle 8i and 9i versions ???
    What's the main feature of PL/SQL in Oracle 10g ???
    Regards

    Hi,
    In SQL 9i there are lot of new syntaxes included.
    with 9i
    1) Scaler subqueries were included(in order by clause and SELECt clause
    2) TimeStamp data type(WITH/WITNOUT TIMEZONE) introduced and along with other relevant date conversion functions introduced
    3) WITH clause introduced for storing the subqueries temporarily in the session
    3) MERGE statement is one more new DML introduced in 9i
    4) Few functions introduced in 9i such as NVL2,COALACE,CASE, DECODe etc.
    5) Few more join types introduced, with some new keywords like USING, ON etc. also new Join Syntax introduced compatible with ANSI SQL 1999 standards
    also FULL OUTER JOIN made easier without using UNION clauses.
    6) iSQL Plus introduced that is a GUI version of CUI SQL PLUS
    7) For the grouping mechanism, GROUPING and GROUPING SETS are 2 new functiosn introduced.
    8) Multitable INSERT statements for different purposes other than normal OLTP work.
    9) Enhancements in PLSQL, EXECUTE IMMEDIATE
    10) Few more Oracle Supplied Packages made available.
    11) ALTER TABLE syntax for changin LONG column to LOB introduced.
    I have tried to put here whatever i cud remember with the help of my notebooks and docs.
    Thanks
    Regards
    Abhivyakti

Maybe you are looking for

  • Oracle 9i monitoring scripts in HACMP 5.4

    Hi, I have installed Oracle 9.2.0.8 on AIX 5.3 (HACMP 5.4) in active passive cluster. I have made startup and shutdown scripts for Oracle. Can anyone please guide me or point me to some link for the monitoring scripts for Oracle in HACMP so that fail

  • Standard Business Content - Loan Management & Term Deposit

    Hi ALL, I would like to does anyone has used Business Content Cubes on Loan Management & Term Deposit and its report, please advise me which cube appropriate Thanks BR Nathan

  • [SOLVED] Need help with simple a script.

    Hello, Iam searching for a small script that sorts my folders in alphabetical order. I want the script to create folder from A to Z and then move every folder that begins with A into the A folder etc etc.. I really hope anyone understands what im sea

  • Jsf filter.....why doesn't start????????

    Hi guys, excuse me if i repeat a my old post,but now i have more clear ideas about problems. I've developed an authorization filter in my jsf application that when a page is loaded try to find a visit object in the session,if it doesn't find show log

  • CONVERSION_FACTOR_GET

    Hi,   I am trying to same meter reading in transaction EL28 by giving a contract Number.  After Pressing Save button it is giving a message ' Unit of Measure M3 can not be converted into ******'. and also it is advising to look into the above functio