1

I have the following case:

Sample code:

        create table abc(aa char(10));
        insert into abc values('ABC'); 
        --ABC will be padded with 7 blank spaces
        Issue:
        Select * from abc where aa in ('ABC'); 
        --This above statement returns one row with value ABC
        Declare
        v_temp varchar2(10);
        v_aa varchar2(10) := 'ABC';
        Begin
        select aa into v_temp from abc where aa in (v_aa);
        dbms_output.put_line(v_temp);
        end;

--The above pl/sql block one execution prints nothing but if i replace the select inside that block with "select aa into v_temp from abc where aa in ('ABC');" the value will be printed.

Please advice me on the behaviour.

4 Answers 4

2

The issue comes down to whether you use char or varchar2 comparison semantics in your queries. If you have a hard-coded string literal or a char(10) variable, Oracle uses the char comparison semantics which are to ignore the trailing white space. If you have a varchar2(10) variable, Oracle uses the varchar2 comparison semantics which includes the trailing white space. Thus

 select aa 
   into v_temp 
   from abc 
  where aa in (v_aa);

will return a row if v_aa is defined as a char(10) (or if it is replace with a string literal) but not if it is defined as a varchar(10).

This is one of the (many) reasons that most people avoid char data types entirely. Personally, I don't mind the occasional char for truly fixed-width data (i.e. char(1) for flags and char(2) for state codes) even though there is no benefit to using char over varchar2 in those scenarios. For anything that is not fixed-width, however, using a char makes no sense. You're just forcing Oracle to consume more space than it needs to and creating more work for yourself dealing with two sets of string comparison semantics (among other issues).

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Justin for the clarification.
0

even if you use select aa from abc where aa in (cast('ABC' as varchar2(10))); you will get no data because:

with varcha2(10) the length of the value of the field is 3 but with char(10) it is is 10

you need to define the v_aa as char(10):

    Declare
    v_temp varchar2(10);
    v_aa char(10) := 'ABC';
    Begin
    select aa into v_temp from abc where aa in (v_aa);
    dbms_output.put_line(v_temp);
    end;

OUTPUT: ABC

Comments

0

Declare the table with a varchar2:

create table abc (
   aa varchar2(10)
);

Alternatively, declare v_aa as char(10). But I would strongly assume that you should go the varchar2 route.

Update

So, I understand your chars stem back from a migration and you're ok to switch them to varchar2. You might want to run

select 
  'alter table ' || table_name  || 
  ' modify '     || column_name || 
  ' varchar2('   || char_length ||');' stmt
from
  user_tab_columns
where
  data_type = 'CHAR';

This will produce alter table statements (like so:)

alter table ABC modify AA varchar2(10);

which you can then run to change the definitions.

Of course, it (almost) goes without saying that you want to thoroughly test that before you apply it on your production database.

2 Comments

ya this will work, the real porblem is we did migration from ms sql server to oracle, columns with char type in ms sql server got migrated to oracle as char type itself. we have migrated many stored procedures where the situation similar to one i asked occurs. So column in sql with char type is to be migrated to varchar2 ??
In the long run, I believe you'll be far better off if you change the datatyptes in the tables to varchar2.
0

If a VARCHAR2 value is compared to a CHAR value, non-blank-padding semantics are used. But, remember, when you assign a character value to a CHAR variable, if the value is shorter than the declared length of the variable, PL/SQL blank-pads the value to the declared length. Given the declarations

v_aa1 VARCHAR2(10) := 'ABC';
v_aa2 CHAR(10)     := 'ABC';  -- PL/SQL blank-pads value

the following IF condition is false because the value of v_aa2 includes five trailing blanks:

IF v_aa1 = v_aa2 THEN ...

All string literals have datatype CHAR. If both values in a comparison are literals, blank-padding semantics are used. If one value is a literal, blank-padding semantics are used only if the other value has datatype CHAR.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.