Skip to Main Content
  • Questions
  • ORA-01401: Inserted value too large for column

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Sharvil.

Asked: January 04, 2003 - 12:22 pm UTC

Last updated: October 21, 2011 - 3:24 am UTC

Version: 8.1.7

Viewed 50K+ times! This question is

You Asked

Hi Tom,
Thank you so much for what you are doing. Here's an Oracle message that is familiar to many of us developers.
"ORA-01401: Inserted value too large for column"
It doesn't tell you which column is too large, it leaves it to us to figure out which column is causing problem. While inconvenient it is not too bad if you are trying to insert into a table with few columns in it. However, last time I recevied this error message, a procedure was trying to insert values into table with 220 columns! :-) That's when I realized it's time to ask you. Is there an easier way to find out which columns is causing the problem?

At work somoene told me that if this same thing happened in MS ACCESS, it would tell you the column that's causing the problem. Now I know Oracle is the grandfather of the databases, and so there should be nothing that MS Access (out of all the databases on god's great earth) can but Oracle can't do. So I am hoping there is some way you can show us how we can identify the value that's
too large, or the column name in which we are trying to insert. Thank you so
much!

and Tom said...

wouldn't it be cool if we were just like access. wow, I cannot wait for our entire feature set to catch up! (seriously, this is an enhancement I too would like to see).

Here is an idea for you:

scott@ORA920> create or replace procedure gen_crud( p_tname in varchar2 )
2 authid current_user
3 as
4 l_stmt long;
5 l_plist long;
6 l_assign long;
7 l_ins1 long;
8 l_ins2 long;
9 l_upd long;
10 begin
11 for x in
12 ( select column_name,
13 decode(column_id,1,'',','||chr(10)||chr(9) ) sep,
14 column_id,
15 decode( data_type,
16 'DATE', 'to_date(p_' || column_name ||
17 ', ''dd-mon-yyyy hh24:mi:ss'' )',
18 'p_' || column_name ) fixed_cname
19 from user_tab_columns
20 where table_name = upper(p_tname)
21 order by column_id )
22 loop
23 l_plist := l_plist || x.sep || 'p_' || x.column_name ||
24 ' in varchar2 default NULL';
25 l_assign := l_assign || chr(9) || 'begin l_rec.' ||
26 x.column_name || ' := ' || x.fixed_cname ||
27 '; exception when others then ' ||
28 'raise_application_error( -20000-' || x.column_id ||
29 ', ''' || x.column_name || ':'' || sqlerrm ); end;' ||
30 chr(10);
31 l_ins1 := l_ins1 || x.sep || x.column_name;
32 l_ins2 := l_ins2 || x.sep || 'l_rec.' || x.column_name;
33 l_upd := l_upd || x.sep || x.column_name || ' = l_rec.' ||
34 x.column_name;
35 end loop;
36
37 l_stmt := '
38 create or replace package ' || p_tname|| '_crud
39 as
40 procedure do_insert( ' || l_plist || ');
41 procedure do_update( p_rowid in rowid, ' || l_plist || ');
42 end;';
43
44 execute immediate l_stmt;
45
46 l_stmt := '
47 create or replace package body ' || p_tname || '_crud
48 as
49
50 procedure do_insert( ' || l_plist || ')
51 as
52 l_rec ' || p_tname || '%rowtype;
53 begin
54 ' || l_assign || '
55 insert into ' || P_tname || '(' || l_ins1 || ') values (' || l_ins2 || ');
56 end;
57
58 procedure do_update( p_rowid in rowid, ' || l_plist || ' )
59 as
60 l_rec ' || p_tname || '%rowtype;
61 begin
62 ' || l_assign || '
63 update ' || p_tname || ' set ' || l_upd || ' where rowid = p_rowid;
64 end;
65
66 end ' || p_tname || '_crud;';
67
68 execute immediate l_stmt;
69 end;
70 /

Procedure created.

so, now you have a utility routine (not fully baked, I just whipped this up).

scott@ORA920> drop table t;
Table dropped.

scott@ORA920> create table t ( x varchar2(10), y date, z number );
Table created.

scott@ORA920> exec gen_crud( 't' )

PL/SQL procedure successfully completed.

scott@ORA920> @getcode t

scott@ORA920> exec t_crud.do_insert( 'helloworld', '01-jan-2003', 55 );
PL/SQL procedure successfully completed.

scott@ORA920> exec t_crud.do_insert( 'helloworld', '01-jan-2003 11:02:44', 55 );
PL/SQL procedure successfully completed.

scott@ORA920> exec t_crud.do_insert( 'hello world', '01-jan-2003 11:02:44', 55 );
BEGIN t_crud.do_insert( 'hello world', '01-jan-2003 11:02:44', 55 ); END;

*
ERROR at line 1:
ORA-20001: X:ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "SCOTT.T_CRUD", line 10
ORA-06512: at line 1

scott@ORA920> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss';

Session altered.

scott@ORA920> select * from t;

X Y Z
---------- -------------------- ----------
helloworld 01-jan-2003 00:00:00 55
helloworld 01-jan-2003 11:02:44 55

2 rows selected.


all that package did was create a nice package:

create or replace package t_crud
as
procedure do_insert( p_X in varchar2 default NULL,
p_Y in varchar2 default NULL,
p_Z in varchar2 default NULL);
procedure do_update( p_rowid in rowid, p_X in varchar2 default NULL,
p_Y in varchar2 default NULL,
p_Z in varchar2 default NULL);
end;
/
create or replace package body t_crud

as

procedure do_insert( p_X in varchar2 default NULL,
p_Y in varchar2 default NULL,
p_Z in varchar2 default NULL)
as
l_rec t%rowtype;
begin
begin l_rec.X := p_X; exception when others then raise_application_error( -20000-1, 'X:' || sqlerrm ); end;
begin l_rec.Y := to_date(p_Y, 'dd-mon-yyyy hh24:mi:ss' ); exception when others then raise_application_error( -20000-2, 'Y:' || sqlerrm ); end;
begin l_rec.Z := p_Z; exception when others then raise_application_error( -20000-3, 'Z:' || sqlerrm ); end;

insert into t(X,
Y,
Z) values (l_rec.X,
l_rec.Y,
l_rec.Z);
end;
..........


that does the insert but also "validates" the data. Nice thing about this is -- you can put extra auditing, whatever in this package and use it instead of insert update or delete...




Rating

  (41 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Here's another option

eric givler, January 05, 2003 - 3:59 pm UTC

Login to db and find your session. Turn on server side tracing for that session (with binds), run the code, turn off the tracing, and examine the results. This concept is described in a Metalink Note.

Pro*c

rajkumar, July 03, 2003 - 7:20 am UTC

Hi tom,
how to debug in pro*C.

Tom Kyte
July 03, 2003 - 9:14 am UTC

in a debugger? it is just c code.

What to do when you load by SQLLDR

Vaikunt Bhat,, May 19, 2004 - 7:19 am UTC

Hi Tom,
This is a long process but some way out Thank You. But I am now using Sqlloader to load a 140 Column table and getting "RA-01401: inserted value too large for column" error how can I find which column is causing the error.
Thanks a bunch. Great job you are doing.

Tom Kyte
May 19, 2004 - 10:56 am UTC

the data should be in the bad file, you can review that to see.

ora-01401

jimmy, May 25, 2004 - 1:40 pm UTC

I used sqlldr to load a data file,
the error message is ora-01401
"ORA-01401: inserted value too large for column"
no data is loaded and the unload data went to the bad file.
is this saying the whole data file is bad?
I use vi the view data it seems OK.
How could I figure out which column is too small
or the data file is bad?



Tom Kyte
May 25, 2004 - 2:29 pm UTC

if it is not obvious looking at a bad record -- how about you post your ctl file and a bad row.



varchar2 type

Chris, March 30, 2005 - 4:44 pm UTC

Tom,

Great website. This solution above is very helpful. It works fine for me. However looking at the code, I noticed a VARCHAR2 formal parameter is accepting NUMBER and DATE types being passed in (with no to_char function). How come there is no datatype conflict here? Just wondering.

Also, do know if the will be adding this enhancement soon (or have they in 10g)?

Thanks.

Tom Kyte
March 30, 2005 - 5:29 pm UTC

they are implicitly converted.

numbers -> strings -> numbers

dates -> strings -> numbers

lots possible, asuming the right nls settings:

ops$tkyte@ORA9IR2> declare
  2          s       varchar2(20);
  3          d       date;
  4          n       number;
  5  begin
  6          n := 1;
  7          s := n;
  8          d := s;
  9          s := d;
 10          n := s;
 11          dbms_output.put_line( n || ', ' || d || ', ' || s );
 12  end;
 13  /
1, 0000001, 0000001
 
PL/SQL procedure successfully completed.


(nls_date_format was 'j') 

DB Developer

Reader, April 19, 2005 - 1:55 pm UTC

I like to avoid 'ORA-01401: Inserted value too large for column' during loading load by SQL*Loader.
How I can use Length fucntion in fields_conditions of SQLLOADER? If the length of data over 3, data is insert into largae table, else normal table.

Thanks

Tom Kyte
April 19, 2005 - 2:26 pm UTC

the records that are too "wide" would just goto a bad file, you can pick them up there

else, use an external table (9i) and a multi-table insert.

Isolation of 'ORA-01401: Inserted value too large for column' to the actual row value

Gillian Ellis, June 21, 2005 - 8:51 am UTC

Is there a way of finding out exactly which value in the column is causing the error? I have a table that is being updated via a cursor which then populates the table with a loop. I have tested the cursor for loop in a recreated environment with a small number of rows (10) and it works however the real table has 35,000 rows. I would really like to find the actual value causing the problem.

Regards,

Gill

Tom Kyte
June 21, 2005 - 5:01 pm UTC

ops$tkyte@ORA10G> create table t ( x varchar2(5), y varchar2(5) );
 
Table created.
 
ops$tkyte@ORA10G> insert into t values ( 'abcdef', 'abc' );
insert into t values ( 'abcdef', 'abc' )
                       *
ERROR at line 1:
ORA-12899: value too large for column "OPS$TKYTE"."T"."X" (actual: 6, maximum:
5)


In 10g, yes, before that, not in any straightforward manner from the direct insert, no. 

David VanZandt, June 24, 2005 - 11:20 am UTC


strange ora-12899,

sns, August 28, 2005 - 7:51 am UTC

I have the description of a table that is being inserted into and the DML statement along with.  

SQL> desc SVC_RETURN_COMMENT_EURO
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DPS_NUM                                   NOT NULL VARCHAR2(11)
 COMMENT_TYPE                              NOT NULL VARCHAR2(3)
 COMMENT_SEQ_NUM                           NOT NULL NUMBER(3)
 DPS_COMMENT                                        VARCHAR2(50)
 COMMENT_DATE                                       DATE
 TECH_CODE                                          VARCHAR2(7)
 FISCAL_CREATE_WEEK_NUM                             NUMBER


I executed this INSERT..SELECT and got the following error:

SQL> insert into ROLLUP_SVCE.SVC_RETURN_COMMENT_EURO
  2  (dps_num,comment_type,comment_seq_num,
  3   dps_comment,comment_date,tech_code,
  4   fiscal_create_week_num)
  5  SELECT dps_num, comment_type, comment_seq_num,
  6              substr(dps_comment,1,30)dps_comment,comment_date,tech_code,
  7               fiscal_week_num  fiscal_create_week_num
  8                 FROM
  9                    return_comment_euro
 10                   WHERE fiscal_week_num >=( SELECT return_comment_63day from DUAL);
            substr(dps_comment,1,30)dps_comment,comment_date,tech_code,
            *
ERROR at line 6:
ORA-12899: value too large for column
"ROLLUP_SVCE"."SVC_RETURN_COMMENT_EURO"."DPS_COMMENT" (actual: 52, maximum: 50)

If you observe in line 6, I am extracting just 30 characters.  The filed DPS_COMMENT on ROLLUP_SVCE.SVC_RETURN_COMMENT_EURO is 50 characters in size.

I am wondering why Oracle threw this error.

The database version is 10.0.1.4.

Thanks, 

Tom Kyte
August 28, 2005 - 8:33 am UTC

likely you have a multibyte characterset such as UTF8.

You have a field dps_comment that allows for 50 BYTES (not characters, bytes)

you are putting into it 30 characters, which might be 30, 60, 90, or more bytes.

does that fit your profile? the multi-byte part?

good review,

sns, August 28, 2005 - 8:44 am UTC

could you please help me on how to find the character set in my database?

What is multi-byte? Is there a single-byte character set?

thanks,

character set,

sns, August 28, 2005 - 8:48 am UTC

I found out the character set of the database.
SQL> select * from nls_database_parameters where parameter like '%CHARACTERSET';

PARAMETER                      VALUE
------------------------------ ------------------------------------------------------------------------------------------------------------------------
NLS_CHARACTERSET               UTF8
NLS_NCHAR_CHARACTERSET         UTF8

What can be inferred on this if the character set is UTF8?

Thanks, 

Tom Kyte
August 28, 2005 - 9:26 am UTC

what can be inferred is that you have a string in that field such that when you take 30 CHARACTERS, you need 52 bytes to store it.

It is exactly what I thought, you have a 30 byte field and attempting to put 30 UTF8 *characters*, each of which could take 1, 2 or more bytes to store -- it fails.

You'll definitely want to read this:
https://docs.oracle.com#index-GLO

the globalalization support guide.  Here is short excerpt from my forthcoming book on this very topic:

<quote>
Bytes or Characters

The VARCHAR2 and CHAR types support two methods of specifying lengths:
    *    In bytes: VARCHAR2(10 byte). This will support up to 10 bytes of data, which could be as few as two characters in a multibyte character set.
    *    In characters: VARCHAR2(10 char). This will support to up 10 characters of data, which could be as much as 40 bytes of information.

When using a multibyte character set such as UTF8, you would be well advised to use the CHAR modifier in the VARCHAR2/CHAR definition—that is, use VARCHAR2(80 CHAR), not VARCHAR2(80), since your intention is likely to define a column that can in fact store 80 characters of data. You may also use the session or system parameter NLS_LENGTH_SEMANTICS to change the default behavior from BYTE to CHAR. I do not recommend changing this setting at the system level; rather, use it as part of an ALTER SESSION setting in your database schema installation scripts. Any application that requires a database to have a specific set of NLS settings makes for an “unfriendly” application. Such applications generally cannot be installed into a database with other applications that do not desire these settings, but rely on the defaults to be in place.

One other important thing to remember is that the upper bound of the number of bytes stored in a VARCHAR2 is 4,000. However, even if you specify VARCHAR2(4000 CHAR), you may not be able to fit 4,000 characters into that field. In fact, you may be able to fit as few as 1,000 characters in that field if all of the characters take 4 bytes to be represented in your chosen character set! 

The following small example demonstrates the differences between BYTE and CHAR and how the upper bounds come into play. We’ll create a table with three columns, the first two of which will be 1 byte and one character, respectively, with the last column being 4,000 characters. Notice that we’re performing this test on a multibyte character set database using the character set AL32UTF8, which supports the latest version of the Unicode standard and encodes characters in a varyiable length fashion using from 1 to 4 bytes for each character:

ops$tkyte@O10GUTF> select *
  2    from nls_database_parameters
  3   where parameter = 'NLS_CHARACTERSET';
 
PARAMETER                      VALUE
------------------------------ --------------------
NLS_CHARACTERSET               AL32UTF8
ops$tkyte@O10GUTF> create table t
2  ( a varchar2(1),
  3    b varchar2(1 char),
  4    c varchar2(4000 char)
  5  )
  6  /
Table created.

Now, if we try to insert into our table a single character that is 2 bytes long in UTF, we observe the following:

ops$tkyte@O10GUTF> insert into t (a) values (unistr('\00d6'));
insert into t (a) values (unistr('\00d6'))
                          *
ERROR at line 1:
ORA-12899: value too large for column "OPS$TKYTE"."T"."A" 
(actual: 2, maximum: 1)

This example demonstrates two things:

    *    VARCHAR2(1) is in bytes, not characters. We have single Unicode character, but it won’t fit into a single byte. 
    *    As you migrate an application from a single-byte fixed-width character set to a multibyte character set, you might find that the text that used to fit into your fields no longer does. 

The reason for the second point is that a 20-character string in a single-byte character set is 20 bytes long and will absolutely fit in a VARCHAR2(20). However a 20-character field could be as long as 80 bytes in a multibyte character set, and 20 Unicode characters may well not fit in 20 bytes. You might consider modifying your DDL to be VARCHAR2(20 CHAR) or using the NLS_LENGTH_SEMANTICS session parameter mentioned previously when running your DDL to create your tables.

If we insert that single character into a field set up to hold a single character, we will observe the following:

ops$tkyte@O10GUTF> insert into t (b) values (unistr('\00d6'));
1 row created.
ops$tkyte@O10GUTF> select length(b), lengthb(b), dump(b) dump from t;
LENGTH(B) LENGTHB(B) DUMP
---------- ---------- --------------------
         1          2 Typ=1 Len=2: 195,150

That INSERT succeeded, and we can see that the LENGTH of the inserted data is one character—all of the character string functions work “character-wise.” So the length of the field is one character, but the LENGTHB (length in bytes) function shows it takes 2 bytes of storage, and the DUMP function shows us exactly what those bytes are. So, that example demonstrates one very common issue people encounter when using multibyte character sets, namely that a VARCHAR2(N) doesn’t necessarily hold N characters, but rather N bytes.
The next issue people confront frequently is that the maximum length in bytes of a VARCHAR2 is 4,000, and in a CHAR it is 2,000:

ops$tkyte@O10GUTF> declare
  2          l_data varchar2(4000 char);
  3          l_ch   varchar2(1 char) := unistr( '\00d6' );
  4  begin
  5          l_data := rpad( l_ch, 4000, l_ch );
  6          insert into t ( c ) values ( l_data );
  7  end;
  8  /
declare
*
ERROR at line 1:
ORA-01461: can bind a LONG value only for insert into a LONG column
ORA-06512: at line 6

That shows that a 4,000-character string that is really 8,000 bytes long cannot be stored permanently in a VARCHAR2(4000 CHAR) field. It fits in the PL/SQL variable because in PL/SQL a VARCHAR2 is allowed to be up to 32KB in size. However, when it is stored in a table, the hard limit is 4,000 bytes. We can store 2,000 of these characters successfully:

ops$tkyte@O10GUTF> declare
  2          l_data varchar2(4000 char);
  3          l_ch   varchar2(1 char) := unistr( '\00d6' );
  4  begin
  5          l_data := rpad( l_ch, 2000, l_ch );
  6          insert into t ( c ) values ( l_data );
  7  end;
  8  /
 
PL/SQL procedure successfully completed.

ops$tkyte@O10GUTF> select length( c ), lengthb( c )
  2    from t
  3   where c is not null;
 
LENGTH(C)  LENGTHB(C)
---------- ----------
2000       4000

And as you can see, they consume 4,000 bytes of storage.
 

awesome,

sns, August 28, 2005 - 9:52 am UTC

this is pretty good information about character set.

Thanks a lot,

sqlldr to control muti byte characters

Ebrahim, January 26, 2006 - 2:04 pm UTC

Dear Tom,

I have a very restrictive situation here and I need your expert advice. Database is 9.2.0.4, characterset UTF8 on Sun Solaris.

We get feeds from data marts for loading to our international datawarehouse. One of the datafiles has a field called PHYSICAL_LOCATION (defined in the database as nvarchar2 (30) ). The data in this field has the last one or two or three "bytes" chopped off. So the entire field data is good, except this last "character". The users will be OK to live without this last one character (since it is a description field). Due to many reasons, the error can not be corrected on the file; in fact the future feeds will have this same issue.

Now, sqlldr rejects the entire record with "multibyte character error". I am trying to see if somehow we can tell sqlldr to take all good "characters" from the field and leave off the last few bytes (which could be one or two or three bytes of the broken off character) that are bad. I could not use substr function to do this. I get the same multibyte character error.

Can you suggest me a function or a trick to do the job?

The control file has this for the PHYSICAL_RECORD:

PHYSICAL_LOCATION POSITION (1050:1079) CHAR(30) "nvl(rtrim(:physical_location),' ')"

The characterset parameter is set to UTF8 in the control file.

Thanks



Tom Kyte
January 27, 2006 - 8:16 am UTC

...
So the entire field data is good, except this last "character".
.....

that is the definition of oxymoron...


It sounds like the last "character" is NOT allright - that the bytes missing are PART OF a character. This field is in fact what is defined as garbage. The beginning of a multi-byte character is there - but the rest of it must be missing (else sqlldr wouldn't even KNOW that a character is missing!!!!! if the entire character is missing, all of it, sqlldr would not know that - it could not know that!)

downloadin of pro*c complier

vijay, February 26, 2006 - 7:10 am UTC

hello tom
from where & how i can get free downloding of pro*c complier


pro*C complier

vijay sharma, March 12, 2006 - 10:55 am UTC

hello tom
i need pro*C complier.these is my second review to your site.i need very urgentely the complier of pro*C.
if you can provide me then please send me at my e-mail address which is given below

Tom Kyte
March 12, 2006 - 11:58 pm UTC

It is on the installation CD's, install it.

pro*C complier

vijay sharma, March 18, 2006 - 1:18 am UTC

hello tom
i have not ant installation CD of pro*C complier.envn more i can try these complier on my city.but there is no well response.
please tell me that free downloading site for pro*C complier.

Tom Kyte
March 18, 2006 - 4:36 pm UTC

you have the install disks? then you have pro*c, run the installer, it'll be in the developer tools from the main installer menu

pro*C complier

vijay sharma, March 19, 2006 - 12:14 am UTC

hello tom,
i am new in pro*C.to learn pro*C for that i will need pro*C complier.
please give me free downloading site for pro*C complier.than i can start my job in pro*C complier.
please give me WEB-SITE for pro*C complier DOWNLOADING


Tom Kyte
March 19, 2006 - 6:53 am UTC

don't know of one. You have full access to otn.oracle.com, just as I do. pro*c comes with the regular database install, it is not "standalone"

Changing from UTF8 to AL32UTF8

ST, October 05, 2006 - 1:46 pm UTC

Can we change the database characterset from UTF8 to AL32UTF8 as we were getting ORA-01461 errors. If so what care should be taken and what are the steps to perform in order to have a clean transition to AL32UTF8. Thanks

String vs Number

Mark Brady, November 22, 2006 - 2:59 pm UTC

You said ""ORA-12899: value too large for column "OPS$TKYTE"."T"."X" (actual: 6, maximum:
5) In 10g, yes, before that, not in any straightforward manner from the direct
insert, no.

I get this when I try to insert '100' into a varchar2(2) but I get the old useless error when I try to insert a 100 into a number(2).

Why not treat these the same?

Give me the column and the size I tried to insert in the precision error. Am I missing something? Is there a way to get it?


sunny, January 12, 2007 - 2:02 am UTC

i cant find any solution about this error

ORA-01401 when using ORDER BY clause on Oracle XE (Western European) ??

Eduardo Legatti, March 01, 2007 - 3:05 pm UTC

Hi Tom,

This is my first question, then sorry for any mistakes.
I am getting an error ORA-01401 on Oracle XE (Western European) when I use the ORDER BY clause in a column that have more than 999 characters.
Is it a bug or a NLS configuration problem ?

The clients use NLS_LANG="BRAZILIAN PORTUGUESE_BRAZIL.WE8MSWIN1252"

Current Configuration
SGMS> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production


SGMS> select * from nls_session_parameters;
PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   BRAZILIAN PORTUGUESE
NLS_TERRITORY                  BRAZIL
NLS_CURRENCY                   R$
NLS_ISO_CURRENCY               BRAZIL
NLS_NUMERIC_CHARACTERS         ,.
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD/MM/RR
NLS_DATE_LANGUAGE              BRAZILIAN PORTUGUESE
NLS_SORT                       WEST_EUROPEAN
NLS_TIME_FORMAT                HH24:MI:SSXFF
NLS_TIMESTAMP_FORMAT           DD/MM/RR HH24:MI:SSXFF
NLS_TIME_TZ_FORMAT             HH24:MI:SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT        DD/MM/RR HH24:MI:SSXFF TZR
NLS_DUAL_CURRENCY              Cr$
NLS_COMP                       BINARY
NLS_LENGTH_SEMANTICS           BYTE
NLS_NCHAR_CONV_EXCP            FALSE


SGMS> select * from nls_database_parameters;
PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CHARACTERSET               WE8MSWIN1252
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD-MON-RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_SORT                       BINARY
NLS_TIME_FORMAT                HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY              $
NLS_COMP                       BINARY
NLS_LENGTH_SEMANTICS           BYTE
NLS_NCHAR_CONV_EXCP            FALSE
NLS_NCHAR_CHARACTERSET         AL16UTF16
NLS_RDBMS_VERSION              10.2.0.1.0


SGMS> select * from nls_instance_parameters;
PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_SORT
NLS_DATE_LANGUAGE
NLS_DATE_FORMAT
NLS_CURRENCY
NLS_NUMERIC_CHARACTERS
NLS_ISO_CURRENCY
NLS_CALENDAR
NLS_TIME_FORMAT
NLS_TIMESTAMP_FORMAT
NLS_TIME_TZ_FORMAT
NLS_TIMESTAMP_TZ_FORMAT
NLS_DUAL_CURRENCY
NLS_COMP
NLS_LENGTH_SEMANTICS           BYTE
NLS_NCHAR_CONV_EXCP            FALSE

Works Fine if I change the language
SGMS> alter session set nls_language=american;

Session altered.

SGMS> select pro_grupo,pro_classe,pro_item,length(pro_nome_tec) from aet_pro where length(pro_nome_tec) > 999;
 PRO_GRUPO PRO_CLASSE   PRO_ITEM LENGTH(PRO_NOME_TEC)
---------- ---------- ---------- --------------------
        27          1          2                 1310


SGMS> select pro_grupo,pro_classe,pro_item from aet_pro where pro_grupo=27 and pro_classe=1 and pro_item=2 order by pro_nome_tec;
 PRO_GRUPO PRO_CLASSE   PRO_ITEM
---------- ---------- ----------
        27          1          2

WORKS FINE ...


The Problem
SGMS> alter session set nls_language="brazilian portuguese";

Sessão alterada.

SGMS> select pro_grupo,pro_classe,pro_item from aet_pro where pro_grupo=27 and pro_classe=1 and pro_item=2 order by pro_nome_tec;
select pro_grupo,pro_classe,pro_item from aet_pro where pro_grupo=27 and pro_classe=1 and pro_item=2 order by pro_nome_tec
*
ERRO na linha 1:
ORA-01401: valor inserido grande demais para a coluna
ORA-01401: inserted value too large for column


SGMS> select pro_grupo,pro_classe,pro_item from aet_pro where pro_grupo=27 and pro_classe=1 and pro_item=2 order by substr(pro_nome_tec,1,1000);
select pro_grupo,pro_classe,pro_item from aet_pro where pro_grupo=27 and pro_classe=1 and pro_item=2 order by substr(pro_nome_tec,1,1000)
*
ERRO na linha 1:
ORA-01401: valor inserido grande demais para a coluna
ORA-01401: inserted value too large for column

Works fine when I use substr function limiting until 999 characters
SGMS> select pro_grupo,pro_classe,pro_item from aet_pro where pro_grupo=27 and pro_classe=1 and pro_item=2 order by substr(pro_nome_tec,1,999);
 PRO_GRUPO PRO_CLASSE   PRO_ITEM
---------- ---------- ----------
        27          1          2

There is no index created under the PRO_NOME_TEC column
SGMS> desc aet_pro
 Nome                                      Nulo?    Tipo
 ----------------------------------------- -------- ----------------------------
 PRO_GRUPO                                 NOT NULL NUMBER(3)
 PRO_CLASSE                                NOT NULL NUMBER(3)
 PRO_ITEM                                  NOT NULL NUMBER(4)
 PRO_NOME_TEC                                       VARCHAR2(4000)


Any information will be greatly appreciate. Thanks

Cheers
Tom Kyte
March 02, 2007 - 12:55 pm UTC

can you enable sql-trace=true and post the relevant part of the trace file - a bit of it from before the 1401?

ORA-01401 when using ORDER BY clause on Oracle XE (Western European) ??

Eduardo Legatti, March 01, 2007 - 4:12 pm UTC

ORA-01401 when using ORDER BY clause on Oracle XE (Western European) ??

Hi Tom,

I know why using the AMERICAN language the query works fine. It is because the AMERICAN language use NLS_SORT=BINARY instead of BRAZILIAN PORTUGUESE that use NLS_SORT=WEST_EUROPEAN. The problem is that NLS_SORT is derived from NLS_LANGUAGE, then I don't want add NLS_SORT=BINARY variable on the customers client by client to resolve this problem.

Why this problem happens on Oracle XE just when a column ordered contains more than 999 characters ?

Any ideas ?

Cheers
Tom Kyte
March 02, 2007 - 1:00 pm UTC

let's trace it

Pro*C

Sidhu, March 02, 2007 - 1:59 pm UTC

Tom

If you had sent that guy the Pro*C installer CD, it must have reached him by now & he might have installed it and started working ;)

Really difficult to answer such questions. One is supposed to know this much before starting with something, I guess.

Sidhu

ORA-01401 when using ORDER BY clause on Oracle XE (Western European) ??

Eduardo Legatti, March 02, 2007 - 2:12 pm UTC

Hi Tom,

I used the dbms_system.set_sql_trace_in_session in order to generate this trace below:
I just need a confirmation that maybe this below is a bug or not.

/usr/lib/oracle/xe/app/oracle/admin/XE/udump/xe_ora_9426.trc
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
ORACLE_HOME = /usr/lib/oracle/xe/app/oracle/product/10.2.0/server
System name: Linux
Node name: dbsrv
Release: 2.6.13-15-smp
Version: #1 SMP Tue Sep 13 14:56:15 UTC 2005
Machine: i686
Instance name: XE
Redo thread mounted by this instance: 1
Oracle process number: 50
Unix process pid: 9426, image: oracleXE@dbsrv

*** 2007-03-02 15:47:50.815
*** ACTION NAME:() 2007-03-02 15:47:50.814
*** MODULE NAME:(SQL*Plus) 2007-03-02 15:47:50.814
*** SERVICE NAME:(SYS$USERS) 2007-03-02 15:47:50.814
*** SESSION ID:(196.47112) 2007-03-02 15:47:50.814
=====================
PARSING IN CURSOR #2 len=43 dep=0 uid=40 oct=3 lid=40 tim=1145361787905210 hv=2621067465 ad='3edca2c0'
select * from aet_pro order by pro_nome_tec
END OF STMT
PARSE #2:c=8000,e=9705,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=1145361787905193
EXEC #2:c=0,e=76,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1145361787905745
FETCH #2:c=8001,e=7393,p=0,cr=38,cu=0,mis=0,r=0,dep=0,og=1,tim=1145361787913245


For more information I created a thread on
http://forums.oracle.com/forums/thread.jspa?messageID=1717545¿¿

SGMS@XE> alter session set nls_language=american;

Session altered.

SGMS@XE> create table x (name varchar2 (4000));

Table created.

SGMS@XE> insert into x values
2 ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');

1 row created.

SGMS@XE> select length(name) from x;

LENGTH(NAME)
------------
1000

SGMS@XE> alter session set nls_sort=BINARY;

Session altered.

SGMS@XE> select name from x order by name;

NAME
---------------------------------------------------------------------------------------------------

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


SGMS@XE> alter session set nls_sort=WEST_EUROPEAN;

Session altered.

SGMS@XE> select name from x order by name;
select name from x order by name
*
ERROR at line 1:
ORA-01401: inserted value too large for column


Cheers
Tom Kyte
March 04, 2007 - 6:25 pm UTC

why not just use trace right in this session???!?!

I don't see the failing query in the trace file - suggest you make this simplier - no need for another session, just turn on trace and run query and exit sqlplus and show us that trace file

ORA-01401 when using ORDER BY clause on Oracle XE (Western European) ??

Eduardo Legatti, March 04, 2007 - 9:03 pm UTC


Hi Tom,

Now, I am doing this test at home ... really strange because the trace file doesn't show me any error.
Are you be able to make this test and reproduce this error too ? Tank you.

SQL> alter session set nls_language=american;

Session altered.
SQL> desc x
 Name             Null?    Type
 ---------------- -------- ----------------------------
 COD                       VARCHAR2(4000)

SQL> select length(cod) from x;

LENGTH(COD)
-----------
       3455

SQL> alter session set tracefile_identifier ="nls_sort_test";

Session altered.

SQL> alter session set sql_trace=true;

Session altered.

SQL> alter session set nls_sort=binary;

Session altered.
SQL> select * from x order by cod;

COD
--------------------------------------------------------------------------------
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x
x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ...

SQL> alter session set nls_sort=west_european;

Session altered.

SQL> select * from x order by cod;
select * from x order by cod
*
ERROR at line 1:
ORA-01401: inserted value too large for column


SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

C:\>


The xe_ora_3828_nls_sort_test.trc trace file
*** TRACE DUMP CONTINUED FROM FILE ***

Dump file c:\oraclexe\app\oracle\admin\xe\udump\xe_ora_3828_nls_sort_test.trc
Sun Mar 04 22:20:42 2007
ORACLE V10.2.0.1.0 - Production vsnsta=0
vsnsql=14 vsnxtr=3
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
Windows XP Version V5.1 Service Pack 2
CPU : 1 - type 586
Process Affinity : 0x00000000
Memory (Avail/Total): Ph:457M/767M, Ph+PgF:1343M/1829M, VA:1704M/2047M
Instance name: xe

Redo thread mounted by this instance: 1

Oracle process number: 18

Windows thread id: 3828, image: ORACLE.EXE (SHAD)


*** 2007-03-04 22:20:42.968
*** ACTION NAME:() 2007-03-04 22:20:42.968
*** MODULE NAME:(SQL*Plus) 2007-03-04 22:20:42.968
*** SERVICE NAME:(SYS$USERS) 2007-03-04 22:20:42.968
*** SESSION ID:(38.24) 2007-03-04 22:20:42.968
=====================
PARSING IN CURSOR #1 len=32 dep=0 uid=36 oct=42 lid=36 tim=6122021411 hv=1569151342 ad='6e220ba0'
alter session set sql_trace=true
END OF STMT
EXEC #1:c=15625,e=668,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6122021403
=====================
PARSING IN CURSOR #2 len=33 dep=0 uid=36 oct=42 lid=36 tim=6131586584 hv=588511850 ad='6e1193bc'
alter session set nls_sort=binary
END OF STMT
PARSE #2:c=0,e=130,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6131586576
EXEC #2:c=0,e=81,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6131588509
*** 2007-03-04 22:20:58.437
=====================
PARSING IN CURSOR #1 len=28 dep=0 uid=36 oct=3 lid=36 tim=6137491485 hv=2664726661 ad='6e22bf3c'
select * from x order by cod
END OF STMT
PARSE #1:c=0,e=197,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6137491477
EXEC #1:c=0,e=127,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6137494664
FETCH #1:c=0,e=524,p=0,cr=7,cu=0,mis=0,r=1,dep=0,og=1,tim=6137495729
FETCH #1:c=0,e=42,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6137497073
STAT #1 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=7 pr=0 pw=0 time=247 us)'
STAT #1 id=2 cnt=1 pid=1 pos=1 obj=13836 op='TABLE ACCESS FULL X (cr=7 pr=0 pw=0 time=150 us)'
*** 2007-03-04 22:21:08.906
=====================
PARSING IN CURSOR #2 len=40 dep=0 uid=36 oct=42 lid=36 tim=6147967642 hv=3066815499 ad='6e2081a0'
alter session set nls_sort=west_european
END OF STMT
PARSE #2:c=0,e=122,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6147967634
EXEC #2:c=0,e=89,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6147970095
*** 2007-03-04 22:21:21.796
=====================
PARSING IN CURSOR #1 len=28 dep=0 uid=36 oct=3 lid=36 tim=6160853059 hv=2664726661 ad='6e22bf3c'
select * from x order by cod
END OF STMT
PARSE #1:c=0,e=200,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6160853050
EXEC #1:c=0,e=112,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=6160856242
FETCH #1:c=0,e=2209,p=0,cr=5,cu=0,mis=0,r=0,dep=0,og=1,tim=6160859046
STAT #1 id=1 cnt=0 pid=0 pos=1 obj=0 op='SORT ORDER BY (cr=0 pr=0 pw=0 time=21 us)'
STAT #1 id=2 cnt=1 pid=1 pos=1 obj=13836 op='TABLE ACCESS FULL X (cr=5 pr=0 pw=0 time=131 us)'
*** 2007-03-04 22:21:55.187
XCTEND rlbk=0, rd_only=1


For a while, I needed to create this trigger below to "resolve" temporarialy the problem ...

create or replace trigger trg_nls_sort
after logon ON schema
begin
execute immediate 'alter session set nls_sort=binary';
end;
/

ORA-01401 when using ORDER BY clause on Oracle XE (Western European) ??

Eduardo Legatti, March 08, 2007 - 4:08 pm UTC

Hi Tom,

Any feedback ?

Cheers
Tom Kyte
March 08, 2007 - 8:37 pm UTC

I've reproduced - but don't as yet has "the answer" - asking around.

How to Truncate inserted values.

cPiyush, May 18, 2007 - 7:51 am UTC

Hi Tom,

I am receiving error "Inserted value too large..." for a VARCHAR2 column, But as this info is not toooo useful in my DB,(But still I have to have this column) can you tell me how to set the truncate option to ON, so that it inserts a row even if it contains larger values(just like mysql).

Thanks,
cPiyush
Tom Kyte
May 18, 2007 - 4:08 pm UTC

gosh, why not just drop this column, you must not need it after all.


umm, application has bug, fix application?

could I show you a technique to do this?
yes

will i?
no

why?
really bad idea... horrible idea. idea that will in a year or two have someone wanting to jump out the window...

I would hate it if someone put a bomb into my database like that.

Inserted data too large

cPiyush, May 20, 2007 - 11:57 pm UTC

Hey Tom,

I agree with your point that this will be a like a bomb in the db.

Then What should I do...can you just suggest me something...

[I can't drop this column at all..:-(]

Regards.
Tom Kyte
May 21, 2007 - 10:21 am UTC

FIX THE APPLICATION

as stated. It has what most of the world would define as "a bug"

It accepts inputs from the end user that cannot be stored. This is no different than an application trying to save "hello world" in a number field.

Why ORA-01401

A reader, June 25, 2008 - 7:52 am UTC

Tom,

Why I get ORA-01401 during SELECT?

SQL> select count(*) TOTAL_STARTUP_OP from sys.dba_common_audit_trail where sql_text like 'STARTUP';
select count(*) TOTAL_STARTUP_OP from sys.dba_common_audit_trail where sql_text like 'STARTUP'
*
ERROR at line 1:
ORA-01401: inserted value too large for column
Tom Kyte
June 25, 2008 - 8:53 am UTC

do you have fine grained access control implemented there. do you have a routine being triggered.


turn on tracing as well, see what sql is taking place under the covers.

A reader, June 25, 2008 - 11:07 am UTC

Tom,

I traced my own session:

SQL> select count(*) from sys.dba_common_audit_trail where sql_text like 'STARTUP';
select count(*) from sys.dba_common_audit_trail where sql_text like 'STARTUP'
*
ERROR at line 1:
ORA-01401: inserted value too large for column


SQL> alter session set events '10046 trace name context off';

After parsing trace file I can see only two sqls in the tkprof output file (one for select and one for alter session above).

If my select triggered some inserts which cause the error above - how can I trace this. We definitely not set up FGA.
Tom Kyte
June 25, 2008 - 11:50 am UTC

any auditing at all

what version

any triggers (event triggers, like on servererror)


what do you mean by "parsing trace file"

ORA-01401: Inserted value too large for column

Shiv, August 27, 2008 - 5:17 am UTC

I am just wondering how this error can come when we are inserting huge value for the chracter ( or varchar) datatype. Incase inserted values are bigger than there should be data truncation only and not the error. This error should occur for if we are inserting a bigger value in the number data type. Isn't? Please correct me if i have got the concept wrongly.
Tom Kyte
August 27, 2008 - 9:43 am UTC

you would then explicitly insert into that table using substr, the database (thankfully) will not silently 'truncate' things for you.

insert into t ( a, b, c ) values ( substr( :bv1, 1, 10 ), substr( :bv2, 1, 30 ), .... );


You could "trick it out" using an instead of trigger on a view, but that would be so wrong - I hate that I even said it.


Use substr, be explicit, do it right - do it on purpose - do it clearly so every one can clearly see what is going on.

Rounding numbers

Gary, August 27, 2008 - 9:13 pm UTC

"you would then explicitly insert into that table using substr, the database (thankfully) will not silently 'truncate' things for you. "

It does for numbers. Okay, it rounds rather than truncates.

create table test (v number(2,1));
insert into test (v) values (3.23);
insert into test (v) values (3.26);
select v from test;
V
---------------
3.20
3.30
Of course if it didn't, you'd have to add in a lot of ROUND functions if you are trying to deal with values that may end up as a recurring decimal (eg .33333). And specifying the column's precision in all those SQLs would turn into a maintenance nightmare.

It is a good reason for being precise about your precision.

Tom Kyte
August 29, 2008 - 1:34 pm UTC

right, but you are not saying "silently truncating a string is a good idea" are you?

column size

A reader, May 06, 2009 - 6:07 pm UTC


ORA-01401 During Import

A reader, September 24, 2009 - 4:25 am UTC

By exp/imp data from prod to test db we got ORA-01401

Both databases are:

NLS_LENGTH_SEMANTICS BYTE

NLS_NCHAR_CHARACTERSET AL16UTF16

NLS_RDBMS_VERSION 9.2.0.5.0

We get this error actually only with few rows of one table. Desc returns exactly the same results on both prod and test.

SQL> desc mytable;
.....
mycolumn NOT NULL VARCHAR2(60 CHAR)
....

If I use length, lengthb on the prod for affected rows I got the following:

1 select mycolumn_id, length(mycolumn), lengthb(mycolumn) from mytable where mycolumn_id in (****)
SQL> /
912116 64 64

Does this means that I ALREADY have 64 (!) character saved in the varchar2 (60 char)column on the PRODdatabase? This is really a 64-char string (a company name counting all ',' and ' ' in the string). How it is possible?
Tom Kyte
September 29, 2009 - 7:35 am UTC

what is your CHARACTER SET - not the nchar character set, we are not looking at an nchar column, just a plain varchar2 columns.

something does look amiss here - did this database undergo a character set change? give me some history

A reader, September 30, 2009 - 3:47 am UTC

NLS_CHARACTERSET = UTF8

Sorry, I can't provide much of "database history". It was "moved" to our group during re-organization of our business....I wonder how I can find any history of such conversion now.

The "odd" thing is that it seems that we really have 64 characters stored in varchar2 (60 char) column on prod. 
Select dump(...) shows this (but simple select truncates to 60 chars). In this way I can understand ORA-01401 during import and probably can avoid this errors by pre-creating table on TEST with for e.g. varchar2 (90 char) and importing with IGNORE=Y, but what I don't understand how it was possible to save 64 chars in (60 char) on the PROD.

set linesize 180

SQL> select control_account_desc,  control_account, length(control_account_desc) length, lengthb(control_account_desc) from gdis.gdis_control_account where control_account in ('*****');

Pant Nagar, Uttaranchal, IN - Spicer India Limited Axle Divi 912116             64                         64


The string "Pant Nagar, Uttaranchal, IN - Spicer India Limited Axle Divi" does not make much sense until it is exactly 60 chars!

SQL> select length('Pant Nagar, Uttaranchal, IN - Spicer India Limited Axle Divi') from dual;

                                                            60

"Pant Nagar, Uttaranchal, IN - Spicer India Limited Axle Division" would make more sense, isn't it? And it is exactly 4 chars more!

SQL> select length('Pant Nagar, Uttaranchal, IN - Spicer India Limited Axle Division') from dual;

                                                               64
But look into dump of the string (especially last 8 chars)

SQL> select control_account_desc,  control_account, length(control_account_desc) length, lengthb(control_account_desc), dump(control_account_desc)dump from gdis.gdis_control_account where co
ntrol_account in ('******');

Pant Nagar, Uttaranchal, IN - Spicer India Limited Axle Divi 912116             64                         64
Typ=1 Len=64: 80,97,110,116,32,78,97,103,97,114,44,32,85,116,116,97,114,97,110,99,104,97,108,44,32,73,78,32,45,32,83,112,105,99,101,114,32,73,110,100,105,97,32,76,105,109,105,116,1
01,100,32,65,120,108,101,32,68,105,118,105,115,105,111,110

SQL> select dump('Division') dump from dual;

Typ=96 Len=8: 68,105,118,105,115,105,111,110

Dump shows that actually 'Division' saved in the table and it shows 64 chars saved in varchar2 (60 char).

Tom Kyte
October 07, 2009 - 7:56 am UTC

One would need the history - I'll have to guess that at one point, this was not a UTF8 database, it was converted and converted "wrong".

A reader, October 21, 2009 - 7:29 am UTC

Tom,

Is it possible to submit a short "not published - seen only by you" comment to this question?


Tom Kyte
October 23, 2009 - 11:54 am UTC

no, there isn't.

you are anonymous, go for it.

Problem with numbers!

Andrey Khataev, October 20, 2011 - 7:21 am UTC

Dear Mr. Tom!
I've found one upsetting moment! Your method works only with string fields. This assignment won't cause en exception if precision of number field in record is smaller than number itself:

rec.number_field := 123456;

field is declared as
create table xxx (
number_field number(3)
)

Record would be filled and we would get an error on insert into table only!
Error is different, but similar:

ORA-01438: value larger than specified precision allowed for this column

Can You tell me something about it? It is so inconvenient to make separate validation for number fields. I should attract oracle table metadata to do what seems to me must Oracle do.
Tom Kyte
October 20, 2011 - 8:05 am UTC

ops$tkyte%ORA11GR2> create table t ( x number(3) );

Table created.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> declare
  2          l_rec t%rowtype;
  3  begin
  4          l_rec.x := 123456;
  5  end;
  6  /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: number precision too large
ORA-06512: at line 4


I'm not sure what you mean.

My previous message needs to be specified

Andrey Khataev, October 20, 2011 - 8:49 am UTC

This problem has place only if you assign constant number into column! If you pass larger number through variable, even of type of a column - assignmebt passes sucessfully

Feel the difference

CREATE TABLE tbl (col NUMBER(3));

declare
n tbl%ROWTYPE;

PROCEDURE fill_rec
AS
rec tbl%ROWTYPE;
BEGIN
rec.col := 1234;
END;

PROCEDURE fill_rec1(col tbl.col%TYPE)
AS
rec tbl%ROWTYPE;
c tbl.col%TYPE;

BEGIN
c := col;
rec.col := col;
END;

begin
fill_rec; -- causes exception
fill_rec1(1234); -- won't do it
end;
Tom Kyte
October 20, 2011 - 5:57 pm UTC

again, I cannot reproduce. I attempted in 10gr2 (10.2.0.5) and 11gr2 (11.2.0.2)

ps$tkyte%ORA10GR2> CREATE TABLE tbl (col NUMBER(3));

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> declare
  2    n tbl%ROWTYPE;
  3
  4    PROCEDURE fill_rec
  5     AS
  6            rec tbl%ROWTYPE;
  7     BEGIN
  8            dbms_output.put_line( 'fill rec running' );
  9            rec.col := 1234;
 10            dbms_output.put_line( 'fill rec succeeded' );
 11     END;
 12
 13     PROCEDURE fill_rec1(col tbl.col%TYPE)
 14     AS
 15            rec tbl%ROWTYPE;
 16            c tbl.col%TYPE;
 17
 18     BEGIN
 19            dbms_output.put_line( 'fill rec(' || col || ') running' );
 20            c := col;
 21            rec.col := col;
 22            dbms_output.put_line( 'fill rec(' || col || ') succeeded' );
 23     END;
 24
 25  begin
 26    fill_rec1(1234); -- won't do it
 27    fill_rec; -- causes exception
 28  end;
 29  /
fill rec(1234) running
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: number precision too large
ORA-06512: at line 20
ORA-06512: at line 26



both of them fail.



please use my technique of a cut and paste directly from sqlplus showing your work and tell us your specific database version.

my results

Andrey Khataev, October 21, 2011 - 1:49 am UTC

Version I'm producing such behavior is 10.2.0.1.0;
Other versions I've tried after your last message are 9.2.0.8.0 and 11th and they both raise exceptions in both functions.

Is this a bug of 10.2.0.1.0 ?

Tom Kyte
October 21, 2011 - 3:24 am UTC

sure sounds like it...

thanks

Andrey Khataev, October 21, 2011 - 7:07 am UTC

Thank You for response

Not a question

Khalid, May 09, 2015 - 3:49 pm UTC

Just making a comment: man this post is fantastic! especially Tom's solution offered right on top in 2011? I remind myself, I need to be looking up asktom more often.

Tom you are a Jedi of the highest order.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library