Bagi Chandrakasan
Oracle ORA-29275 Partial Multi-byte error

Oracle ORA-29275 Partial Multi-Byte Error


ORA-29275 Partial multibyte character

Occasionally partial data is stored in the oracle database due to loading or character set errors. When selecting these records, Oracle will throw ORA-29275 Partial multibyte character error. If due to character set issue, CONVERT function can be used to convert to proper character set.

Though you’ll be able to run commands like CTAS without issues, any attempt to fetch the row will result in the error message. If you’re migrating to a different database platform - say using AWS DMS, the load will fail until the error is corrected.

The common error due to character set can be fixed with CONVERT as described here.

More often than not, the data itself is the issue - sometimes truncated by substrb to fit the length, sometimes extracted and loaded using wrong character set which cannot be fixed using the convert function.

Identifying the offending records

This is usually the hardest part especially if the table is large. One option is to split the selects into smaller subset until the offending rows were found.

The first option i tried after lot of online search is to append a NULL to the string and check the length - like this:


-- Assuming the "city" field has the bad data:
select emp_id, emp_name, dump(city),lengthb(city) from emp
where lengthb(city) != lengthb(city || null);

update emp
  set city = city || null
  where lengthb(city) != lengthb(city || null);

commit;

If there’s an hit, the offending record is identified. However, this fixes only the last byte. If the field has multiple partial multi-bytes, after fixing the record once, the same record will keep popping up as error and the process needs to be repeated.

The second option i found is to use the to_nchar function - this supposedly discards the partial characters.


-- Assuming the "city" field has the bad data:
select emp_id, emp_name, dump(city),lengthb(city) from emp
where lengthb(city) != lengthb(to_nchar(city));

-- Using MOD
select emp_id, emp_name, dump(city),lengthb(city) from emp
where mod(lengthb(city),lengthb(to_nchar(city))) > 0;

update emp
  set city = to_nchar(city)
  where lengthb(city) != lengthb(to_nchar(city));

commit;

The to_nchar method is able to identify fields that weren’t caught using the null append method.

Surely, there are more ways to address these. Use what works best.