From: riverdance on
On Jun 8, 11:58 am, ddf <orat...(a)msn.com> wrote:
> Comments embedded.
> On Jun 8, 10:45 am, riverdance <esthershe...(a)yahoo.com> wrote:
>
> > HI,
>
> > sorry , I'm new to oracle world..
>
> No need to apologize.
>
> > who could help explain following.. I expected following SQL would
> > error out.. but I got following result.
>
> >  I don't understand, how date format string '1/1/2010' could convert
> > to number .000497512, and how date format string 1-1-2010 could
> > convert to number -2010?
>
> They're not strings, they are numeric calculations:
>
> 1/1/2010 == 1 divided by 1 divided by 2010 ==  .000497512
>
> 1-1 2010 == 1 minus 1 minus 2010 == -2010
>
> > SQL> select nvl2(birth_dt,0,1/1/2010) from eshen.test;
>
> > NVL2(BIRTH_DT,0,1/1/2010)
> > -------------------------
> >                .000497512
> >                .000497512
>
> > SQL> select nvl2(birth_dt,0,1-1-2010) from eshen.test;
>
> > NVL2(BIRTH_DT,0,1-1-2010)
> > -------------------------
> >                     -2010
> >                     -2010
>
> Date strings would be '1/1/2010' or '1-1-2010', including the single
> quotes, and would be used with the to_date function:
>
> SQL> create table test(name  varchar2(30), birth_dt date);
>
> Table created.
>
> SQL>
> SQL> begin
>   2          for i in 1..100 loop
>   3                  if mod(i,2) = 0 then
>   4                  insert into test(name, birth_dt)
>   5                  values('Narmo'||i, sysdate - (10*i));
>   6                  else
>   7                  insert into test(name)
>   8                  values('Narmo'||i);
>   9                  end if;
>  10          end loop;
>  11
>  12          commit;
>  13  end;
>  14  /
>
> PL/SQL procedure successfully completed.
>
> SQL>
> SQL> --
> SQL> -- These error out with proper dates as return values
> SQL> --
> SQL> select nvl2(birth_dt,0,to_date('1/1/2010', 'mm/dd/rrrr')) from
> test;
> select nvl2(birth_dt,0,to_date('1/1/2010', 'mm/dd/rrrr')) from test
>                        *
> ERROR at line 1:
> ORA-00932: inconsistent datatypes: expected NUMBER got DATE
>
> SQL> select nvl2(birth_dt,0,to_date('1-1-2010', 'mm-dd-rrrr')) from
> test;
> select nvl2(birth_dt,0,to_date('1-1-2010', 'mm-dd-rrrr')) from test
>                        *
> ERROR at line 1:
> ORA-00932: inconsistent datatypes: expected NUMBER got DATE
>
> SQL> --
> SQL> -- These don't error but don't return the value you wanted
> SQL> --
> SQL>
> SQL> select nvl2(birth_dt,sysdate,to_date('1/1/2010', 'mm/dd/rrrr'))
> from test;
>
> NVL2(BIRT
> ---------
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
>
> NVL2(BIRT
> ---------
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
>
> ...
> 100 rows selected.
>
> SQL> select nvl2(birth_dt,sysdate,to_date('1-1-2010', 'mm-dd-rrrr'))
> from test;
>
> NVL2(BIRT
> ---------
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
>
> NVL2(BIRT
> ---------
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
> 01-JAN-10
> 08-JUN-10
>
> ...
>
> 100 rows selected.
>
> SQL>
> SQL> --
> SQL> -- These give you the 0 you want but have more gyrations to
> return the date you coded and do so in Julian format
> SQL> -- as that 'date' is actually a number
> SQL> --
> SQL> select nvl2(birth_dt,0,to_number(to_char(to_date('1/1/2010', 'mm/
> dd/rrrr'),
>  'J'))) from test;
>
> NVL2(BIRTH_DT,0,TO_NUMBER(TO_CHAR(TO_DATE('1/1/2010','MM/DD/
> RRRR'),'J')))
> -------------------------------------------------------------------------
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> ...
>
> 100 rows selected.
>
> SQL> select nvl2(birth_dt,0,to_number(to_char(to_date('1-1-2010', 'mm-
> dd-rrrr'),
>  'J'))) from test;
>
> NVL2(BIRTH_DT,0,TO_NUMBER(TO_CHAR(TO_DATE('1-1-2010','MM-DD-
> RRRR'),'J')))
> -------------------------------------------------------------------------
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> 0
>
> 2455198
>
> ...
>
> 100 rows selected.
>
> SQL>
>
> David Fitzjarrell

David, really apprecated!
From: Andrew M on

Another reason to use coalessce is that it will short circuit the
parameters while nvl and nvl2 will not. This might seem trivial and
is if your arguments are literals or columns. But if they are
functions, sequences or some computed value it can make a difference
in performance or correct data.

sql->create or replace package atst
2 as
3
4 function getNextVal return number;
5 end;
6 /

Package created.

Elapsed: 00:00:00.02
sql->show err
No errors.
sql->
sql->--------------------------------------
sql->create or replace package body atst
2 as
3
4 x number;
5
6 function getNextVal return number
7 is
8 begin
9 x := x + 1;
10 return x;
11 end;
12
13
14 begin
15 x := 0;
16 end;
17 /

Package body created.

Elapsed: 00:00:00.02
sql->show err
No errors.
sql->
sql->col nxtval format 99999
sql->select nvl2(1,atst.getNextVal, atst.getNextVal) nxtval from dual;

NXTVAL
------
1

Elapsed: 00:00:00.00
sql->select nvl2(1,atst.getNextVal, atst.getNextVal) nxtval from dual;

NXTVAL
------
3

Elapsed: 00:00:00.00
sql->select nvl2(1,atst.getNextVal, atst.getNextVal) nxtval from dual;

NXTVAL
------
5

Elapsed: 00:00:00.01
sql->select nvl2(1,atst.getNextVal, atst.getNextVal) nxtval from dual;

NXTVAL
------
7

Elapsed: 00:00:00.00
sql->
sql->--============================================================
sql->select coalesce(atst.getNextVal, atst.getNextVal) nxtval from
dual;

NXTVAL
------
9

Elapsed: 00:00:00.00
sql->select coalesce(atst.getNextVal, atst.getNextVal) nxtval from
dual;

NXTVAL
------
10

Elapsed: 00:00:00.00
sql->select coalesce(atst.getNextVal, atst.getNextVal) nxtval from
dual;

NXTVAL
------
11

Elapsed: 00:00:00.01
sql->select coalesce(atst.getNextVal, atst.getNextVal) nxtval from
dual;

NXTVAL
------
12