Tuesday, September 11, 2007

Data Types - Answers 2 of 4 (varchar2)

 
Way (the heck) back in Oracle 6, that’s 1989 and 5 major releases for those of you who don’t eat, breath, sleep database stuff. Oracle introduced two data types, the varchar and varchar2.
 
The only differences were that the varchar data type was implemented for ANSII standards and it was limited to 2000 bytes. Subsequent releases of Oracle completely replaced the varchar by aliasing it to the varchar2 type.
 
I have heard all sorts of oracle-wives-tales on char and varchar speed advantages verses varchar2. I currently don’t believe any of them.

Rant

Databases tend to be highly technical.  For this reason many people are scared by the technology and turn off their brains, expecting the guru to get the work done. Many self-proclaimed guru’s have taken advantage of this paranoia, creating some kind of mysticism around what databases can or can’t do. They pick and choose what they want to support and dismiss new features by stating that “back in version x feature y was a bad thing.”  Said behavior has been very detrimental to our industry and should be shunned/nipped-in-the-bud when it rears its ugly head...

End Rant

Back to the varchar2 data type. It only takes one argument representing the maximum number of bytes or characters the field should hold. This argument is required and must be at least 1. Its maxim size is 4000 characters.
 
SQL> create table varchar_type (
  2    column_1  varchar(10 char),
  3    column_2  varchar(10),
  4    column_3  varchar2(10 char), -- for utf8 stuff
  5    column_4  varchar2(10)
  6  );
 
Table created.
 
SQL> create table funky_varchar (
  2    column_f  varchar2(0)
  3  );
  column_f  varchar2(0)
                      *
ERROR at line 2:
ORA-01723: zero-length columns are not allowed
 
The varchar and varchar2 data types, for the moment, are exactly the same; however, Oracle strongly cautions against using the varchar type as “(it) is currently synonymous with varchar2, (but) is scheduled to be redefined” (Oracle Database SQL Language Reference, #B28286-01 July 2007).
 
Finally, the variable character type will efficiently store data, using only the space needed, unlike the char data type which right-pads (appends “ “) to the information it holds.
 
SQL> create table test_character (
  2    column_1  char(10),
  3    column_2  varchar2(10)
  4  );
 
Table created.
 
SQL> insert into test_character values ('Red','Red');
 
1 row created.
 
SQL> insert into test_character values ('Blue','Blue');
 
1 row created.
 
SQL> insert into test_character values ('Yellow','Yellow');
 
1 row created.
 
SQL> commit;
 
Commit complete.
 
SQL> select column_1,
  2         length(column_1) size_char,
  3         column_2,
  4         length(column_2) size_varchar2
  5    from test_character;
 
COLUMN_1    SIZE_CHAR COLUMN_2   SIZE_VARCHAR2
---------- ---------- ---------- -------------
Red                10 Red                    3
Blue               10 Blue                   4
Yellow             10 Yellow                 6
 
Notice that the char data type is always 10. You can chew up a-whole-lotta space, real-fast, using the char type. It is antiquated and should not be used. I have only found one good use for it and that is to hold “Y” and “N” flag type information.
 
--example of char use
create table family (
  person_id      number(30),
  father_id      number(30),
  mother_id      number(30),
  first_name     varchar2(50 char),
  middle_name    varchar2(50 char),
  last_name      varchar2(50 char),
  other_name     varchar2(50 char),
  birth_date     date,
  death_date     date,
  ...
  sex            char, -- M or F
  update_ts      timestamp
);
 
create table employee (
  employee_id       number(10),
  manager_id        number(10),
  department_id     number(10),
  first_name        varchar2(50 char),
  middle_name       varchar2(50 char),
  last_name         varchar2(50 char),
  date_hired        date,
  ...
  termination_flag  char, -- Y or N
  update_ts         timestamp
);

Saturday, September 08, 2007

Data Types - Answers 1 of 4 (number)

 
I know several developers who feel that the Oracle number data type is too limiting. In many cases they want to explicitly stipulate types like int and smallint (integer and small integer). I believe that their desire to do so represents a misunderstanding of how the number data type is used, for example:
SQL> create table number_test (
  2    column_1    number(5),
  3    column_2    number(5,3),
  4    column_3    number
  5  );
 
Table created.
 
SQL> insert into number_test
  2    values (1.123,1.123,1.123);
 
1 row created.
 
SQL> commit;
 
Commit complete.
 
SQL> select *
  2    from number_test;
 
  COLUMN_1   COLUMN_2   COLUMN_3
---------- ---------- ----------
         1      1.123      1.123
 
Notice how column 1 became a the whole number 1.  What do you think will happen when we insert a number like 1.75?
 
SQL> update number_test
  2     set column_1 = 1.75;
 
1 row updated.
 
SQL> commit;
 
Commit complete.
 
SQL> select *
  2    from number_test;
 
  COLUMN_1   COLUMN_2   COLUMN_3
---------- ---------- ----------
         2      1.123      1.123
 
SQL>
 
The number rounds itself up to the nearest whole number. It is essentially an int.  I have stipulated that it should be a number(5) which is sufficient for a smallint. If I wanted a bigint, I should specify a larger precision when defining the data type, but no scale.
 
Should I expect the same result from column 3? No! The number specification without precision or scale will represent numbers like 1.234567890... It will not round like the number(5) did. What would happen if I put a number like 123.456 into column 2?

 
 
SQL> update number_test
  2     set column_2 = 123.456;
   set column_2 = 123.456
                  *
ERROR at line 2:
ORA-01438: value larger than specified precision allowed for this column
 
 
SQL> update number_test
  2     set column_2 = 1234.56;
   set column_2 = 1234.56
                  *
ERROR at line 2:
ORA-01438: value larger than specified precision allowed for this column
 
 
SQL>
 
In each case, Oracle threw the “ORA-01438: value larger than specified precision allowed” error.
 
Finally, as of Oracle 11g the number data type will store, “positive and negative fixed numbers with absolute values from 1.0 x 10-130 to but not including 1.0 x 10126” (Oracle Database SQL Language Reference, #B28286-01 July 2007).