ORA-12899 尽管长度相同,列的值太大

ORA-12899 value too large for column despite of same length

我是运行下面的查询。但是得到 ORA-12899。虽然我尝试插入的字符串的长度是 30.

INSERT INTO TABLE1 SELECT * FROM temp_Table1 where LENGTH(column1)=30;

SQL Error: ORA-12899:value too large for column "TABLE1"."column1" (actual: 31, maximum: 30)


select column1 from temp_Table1 where LENGTH(column1)=30;

Testing  - HLC/TC Design Corre

Desc temp_Table1

column1 VARCHAR2(30)

Desc Table1

column1 VARCHAR2(30)

试着改变你的table喜欢

ALTER TABLE1 MODIFY column1 VARCHAR2(30 CHAR)

错误指出您的 column1 最多可以存储 30 个字符,而您在其中传递的字符超过 30 个,这导致了错误。

也可以参考这篇文章:Oracle Database - Bytes or Characters for VARCHAR2 and CHAR

ORA-12899

Often times, as our companies grow and evolve in response to an expansion in the form of client-base, staff, profit or markets, the data associated with this growth will also change. Data systems like Oracle have the innate ability to remain fairly flexible in regards to working with this variance in information. Still, even the most versatile database systems require maintenance and refining in the face of increased data traffic. This work is essential to accommodating any constraints on memory or necessary redefinitions of parameters. The ORA-12899 error is representative of an instance in which either an uptick in data or a user error is forcing Oracle to stall during its requested action.

THE PROBLEM

The ORA-12899 is an Oracle error that occurs when the value entered into the column string is too large. What this means is that an attempt was made by the user to update or insert a column with a value that is too wide for the destination column. The name of a particular column will be given and the actual width of the value, as well as the maximum width permitted for the column, will be associated with that. As mentioned, the value can be given in the form of characters. In the event that the width is reported in characters, this will mean that character length semantics are operating for the column. Otherwise the width will be reported in bytes. Essentially, this error results from trying to push through a value, or set of values, that exceed the specified maximum width of the column. So, how does a user correct this type of error?

THE SOLUTION

To begin, open up the OERR utility. The user will require the full ORA-12899 message to receive the proper feedback on the error. This will provide more information on the error and allow further investigation. Typically, the error can come from one of three sources. The first source is the SQL statements that have been generated. Checking source and destination column data types to discover whether they are compatible with current formats is the second source. Lastly, the user can look at the destination column width – where the value is being assigned – to make sure it is large enough to accommodate the maximum value that the user anticipates assigning. Let us now turn to an example that corrects ORA-12899. Suppose the user has created the following table:

CREATE TABLE Clients(
ClientID varchar2(9) PRIMARY KEY,
Client_Contact varchar2(40) NOT NULL,
Address varchar(20) NOT NULL,
Zip varchar2(5) NOT NULL,
Client_Number varchar2(11) NOT NULL)

The user then attempts to issue an INSERT VALUES statement that looks something like this:

INSERT INTO Clients VALUES(
727546345,
‘Roger Holcomb’,
‘—Benjamin Road Syracuse’,
‘-----‘, 05307623754)

The user might try to run the statement from here, but will receive the following error message:

Error starting at line 7 in command: INSERT INTO Clients VALUES(727546345, ‘Ricky Galorey’, ‘18 Benjamin Road Syracuse’, ‘13208’, 05307623754) Error report: SQL Error: ORA-12899: value too large for column “ORGANIZATIONS”. “MARKET”. “ADDRESS”(actual: 25, maximum: 20) 12899. 00000 – “value too large for column %s (actual: %s, maximum: %s)”

This error statement indicates that the variable ‘Address’ cannot hold more than twenty characters as that would exceed the width of the column parameter. When we look back at the address value (’18 Benjamin Road Syracuse’) we can see that the total number of characters (25) exceeds the maximum number allowed for the width of the column. To correct this, the user can change the VARCHAR2 for address to an amount that can accommodate the typical address length that their company would input.

The above answer original URL

由于目标 table 数据库中的不同 NLS 设置,目标中可能需要更多字节。 尝试将 table 更改为 alter Table1 modify column1 varchar2(30 char)

您看到了 character and byte length semantics:

之间的区别

You must specify a maximum length for a VARCHAR2 column. This maximum must be at least 1 byte, although the actual string stored is permitted to be a zero-length string (''). You can use the CHAR qualifier, for example VARCHAR2(10 CHAR), to give the maximum length in characters instead of bytes. A character is technically a code point of the database character set. You can use the BYTE qualifier, for example VARCHAR2(10 BYTE), to explicitly give the maximum length in bytes. If no explicit qualifier is included in a column or attribute definition when a database object with this column or attribute is created, then the length semantics are determined by the value of the NLS_LENGTH_SEMANTICS parameter of the session creating the object.

如果您的会话使用字节语义,那么您 table 中的列将默认为:

select value from nls_session_parameters where parameter = 'NLS_LENGTH_SEMANTICS';

VALUE                                  
----------------------------------------
BYTE                                    

create table t42(text varchar2(5));

Table T42 created.

select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';

C
-
B

这与显式执行相同:

create table t42(text varchar2(5 byte));

如果您的源数据是五个字符但包含任何多字节字符,那么字节的数量将超过五个:

insert into t42 (text) values ('Hello');

1 row inserted.

insert into t42 (text) values ('Señor');

SQL Error: ORA-12899: value too large for column "SCHEMA"."T42"."TEXT" (actual: 6, maximum: 5)

这就是您所看到的。当您从其他 table 插入值时,您将根据值的长度进行过滤,但 length() 计算字符数而不是字节数。有一个计算字节数的 lengthb() 函数。如果您检查您选择的 30 个字符值的字节长度,您会发现它实际上是 31 个字节,因此其中一个字符是多字节。

with t42 (text) as (
  select 'Hello' from dual
  union all select 'Señor' from dual
  union all select 'Testing  - HLC/TC Design Corre' from dual
)
select text, length(text) as chars, lengthb(text) as bytes, dump(text, 16) as hex
from t42;

TEXT                            CHARS BYTES HEX                                                                                                      
------------------------------- ----- ----- ----------------------------------------------------------------------------------------------------------
Hello                               5     5 Typ=1 Len=5: 48,65,6c,6c,6f                                                                               
Señor                               5     6 Typ=1 Len=6: 53,65,c3,b1,6f,72                                                                            
Testing  - HLC/TC Design Corre     30    31 Typ=1 Len=31: 54,65,73,74,69,6e,67,c2,a0,20,2d,20,48,4c,43,2f,54,43,20,44,65,73,69,67,6e,20,43,6f,72,72,65

dump() 值中,您可以看到在 Testing (54,65,73,74,69,6e,67) 之后和 space 和破折号 (20,2d) 之前,您有 c2,a0,也就是 the UTF-8 multibyte non-breaking space character。 (您经常会在从 Word 文档复制的文本中看到它,以及大引号和其他非 ASCII 范围的字符)。

您可以更改您的插入以过滤 LENGTHB(column1)=30(这将排除您当前找到的行),或者将您的列定义更改为 30 个字符而不是 30 个字节:

drop table t42;

Table T42 dropped.

create table t42(text varchar2(5 char));

Table T42 created.

select char_used from user_tab_columns where table_name = 'T42' and column_name = 'TEXT';

C
-
C

insert into t42 (text) values ('Hello');

1 row inserted.

insert into t42 (text) values ('Señor');

1 row inserted.

或者,如果可能并且对您的数据有意义,则将任何意外的多字节字符替换为等效的单字节字符;在这种情况下,正常的 space 可能 可以工作,但是任何替换都可能破坏实际上可能很重要的信息。