What is the major difference between Varchar2 and char
Just to avoid confusion about much wrong information. Here are some information about difference including performance
Reference: https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2668391900346844476
Since a char is nothing more than a VARCHAR2 that is blank padded out to the maximum length - that is, the difference between the columns X and Y below:
create table t ( x varchar2(30), y char(30) ); insert into t (x,y) values ( rpad('a',' ',30), 'a' );
IS ABSOLUTELY NOTHING, and given that the difference between columns X and Y below:
insert into t (x,y) values ('a','a')
is that X consumes 3 bytes (null indicator, leading byte length, 1 byte for 'a') and Y consumes 32 bytes (null indicator, leading byte length, 30 bytes for 'a ' )
Umm, varchar2 is going to be somewhat "at an advantage performance wise". It helps us NOT AT ALL that char(30) is always 30 bytes - to us, it is simply a varchar2 that is blank padded out to the maximum length. It helps us in processing - ZERO, zilch, zippo.
Anytime you see anyone say "it is up to 50% faster", and that is it - no example, no science, no facts, no story to back it up - just laugh out loud at them and keep on moving along.
There are other "made up things" on that page as well, for example:
"Searching is faster in CHAR as all the strings are stored at a specified position from the each other, the system doesnot have to search for the end of string. Whereas in VARCHAR the system has to first find the end of string and then go for searching."
FALSE: a char is just a varchar2 blank padded - we do not store strings "at a specified position from each other". We do search for the end of the string - we use a leading byte length to figure things out.
Simple example to show the difference:
SELECT
'"'||CAST('abc' AS VARCHAR2(10))||'"',
'"'||CAST('abc' AS CHAR(10))||'"'
FROM dual;
'"'||CAST('ABC'ASVARCHAR2(10))||'"' '"'||CAST('ABC'ASCHAR(10))||'"'
----------------------------------- -------------------------------
"abc" "abc "
1 row selected.
The CHAR is usefull for expressions where the length of charaters is always fix, e.g. postal code for US states, for example CA, NY, FL, TX
Although there are already several answers correctly describing the behaviour of char
, I think it needs to be said that you should not use it except in three specific situations:
- You are building a fixed-length file or report, and assigning a non-null value to a
char
avoids the need to code anrpad()
expression. For example, iffirstname
andlastname
are both defined aschar(20)
, thenfirstname || lastname
is a shorter way of writingrpad(firstname,20) || rpad(lastname,20)
to createChuck Norris
. - You need to distinguish between the explicit empty string
''
andnull
. Normally they are the same thing in Oracle, but assigning''
to achar
value will trigger its blank-padding behaviour whilenull
will not, so if it's important to tell the difference, and I can't really think of a reason why it would be, then you have a way to do that. - Your code is ported from (or needs to be compatible with) some other system that requires blank-padding for legacy reasons. In that case you are stuck with it and you have my sympathy.
There is really no reason to use char
just because some length is fixed (e.g. a Y/N
flag or an ISO currency code such as 'USD'
). It's not more efficient, it doesn't save space (there's no mythical length indicator for a varchar2
, there's just a blank padding overhead for char
), and it doesn't stop anyone entering shorter values. (If you enter 'ZZ'
in your char(3)
currency column, it will just get stored as 'ZZ '
.) It's not even backward-compatible with some ancient version of Oracle that once relied on it, because there never was one.
And the contagion can spread, as (following best practice) you might anchor a variable declaration using something like sales.currency%type
. Now your l_sale_currency
variable is a stealth char
which will get invisibly blank-padded for shorter values (or ''
), opening the door to obscure bugs where l_sale_currency
does not equal l_refund_currency
even though you assigned 'ZZ'
to both of them.
Some argue that char(n)
(where n is some character length) indicates that values are expected to be n characters long, and this is a form of self-documentation. But surely if you are serious about a 3-character format (ISO-Alpha-3 country codes rather than ISO-Alpha-2, for example), wouldn't you define a constraint to enforce the rule, rather than letting developers glance at a char(3)
datatype and draw their own conclusions?
CHAR
was introduced in Oracle 6 for, I'm sure, ANSI compatibility reasons. Probably there are potential customers deciding which database product to purchase and ANSI compatibility is on their checklist (or used to be back then), and CHAR
with blank-padding is defined in the ANSI standard, so Oracle needs to provide it. You are not supposed to actually use it.