Reputation: 689
Given the table ATABLE
with a field AFIELD
of type CHAR(8)
, and where i have a field with value "1234567 "
Why, in SQL Developer, if I query:
SELECT * FROM ATABLE WHERE AFIELD = '1234567';
It will automatically pad the missing space and return the results, and if I query with :
SELECT * FROM ATABLE WHERE AFIELD = :value;
and input the value, it wont ?
Upvotes: 0
Views: 683
Reputation: 191255
Within expressions and conditions, Oracle treats text literals as though they have the data type CHAR by comparing them using blank-padded comparison semantics.
When you do WHERE AFIELD = '1234567'
the text literal '1234567'
is treated as char
and blank-padded comparison semantics are used to compare the column value and the literal. Even though the literal doesn't have the trailing space, those semantics see them as the same, so it finds a match.
When you use a bind variable the literal you assign to it is a char
, but the bind variable itself is varchar2
- even if you declare it as char
, oddly, though in that case the value is blank-padded anyway:
var char_value char(8);
exec :char_value := '1234567';
var varchar2_value varchar2(8);
exec :varchar2_value := '1234567';
select dump('1234567') as d1, dump(:char_value) as d2, dump(:varchar2_value) as d3
from dual;
D1 D2 D3
------------------------------------ ------------------------------------ ------------------------------------
Typ=96 Len=7: 49,50,51,52,53,54,55 Typ=1 Len=8: 49,50,51,52,53,54,55,32 Typ=1 Len=7: 49,50,51,52,53,54,55
The text literal is data type 96 (char
), while both bind variables are type 1 (varchar
/varchar2
); but notice the char_value
bind variable has the trailing space, with length 8 and the last character as code point 32.
When you compare your char
column value with a varchar2
bind variable the column value is implicitly converted from char
to varchar2
:
The following rules govern implicit data type conversions:
- During SELECT FROM operations, Oracle converts the data from the column to the type of the target variable.
So your space-padded char(8)
column value is implicitly converted to varchar2(8)
to match the bind variable's data type, and then because they are varchar2
the nonpadded comparison semantics are used.
When you compare your char(8)
column with the supposedly-char(8)
bind variable, you're actually comparing with a padded varchar2(8)
- but both the implicitly converted column value and the blank-padded bind variable are actually the same, both with the trailing space; '1234567 '
is the same as '1234567 '
, so there is a match, even with nonpadded comparison semantics.
With the varchar2(8)
bind variable the same thing happens, but now the bound value is not padded, and as you are using nonpadded comparison semantics to compare '1234567 '
with '1234567'
- they are not the same, so there is no match, and no data is returned by the query.
As @a_horse_with_no_name said you should almost always use varchar2
rather than char
. But if you must use it and are stuck with it then at least make sure you use the same data type for comparisons.
Upvotes: 1
Reputation: 314
You are right
SELECT * FROM ATABLE WHERE AFIELD = :value;
does not work with CHAR as you desire.
Anyway I have noticed that the following query works as you desire:
SELECT * FROM ATABLE WHERE AFIELD = &value;
If you use &value in several places, you can use &&value (double &) the first time (and &value elsewhere), in order to avoid to input the same value several times; when you have to change that value, you can undefine it with:
undef value;
Upvotes: 1