尽管长度相同,ORA-12899的值对于色谱柱来说太大了

Shi*_*itu 8 sql oracle varchar varchar2

我正在运行以下查询.但得到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)
Run Code Online (Sandbox Code Playgroud)

Ale*_*ole 9

您将看到字符和字节长度语义之间的区别:

您必须为VARCHAR2列指定最大长度.尽管存储的实际字符串允许为零长度字符串(''),但此最大值必须至少为1个字节.您可以使用CHAR限定符(例如VARCHAR2(10 CHAR))以字符而不是字节给出最大长度.从技术上讲,字符是数据库字符集的代码点.您可以使用BYTE限定符(例如VARCHAR2(10 BYTE))显式地给出最大长度(以字节为单位).如果在创建具有此列或属性的数据库对象时,列或属性定义中不包含显式限定符,则长度语义由创建对象的会话的NLS_LENGTH_SEMANTICS参数的值确定.

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

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
Run Code Online (Sandbox Code Playgroud)

这与明确做的相同:

create table t42(text varchar2(5 byte));
Run Code Online (Sandbox Code Playgroud)

如果源数据是五个字符但包含任何多字节字符,则字节数将超过五个:

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)
Run Code Online (Sandbox Code Playgroud)

这就是你所看到的.当您插入其他表中的值时,您将过滤值的长度,但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
Run Code Online (Sandbox Code Playgroud)

dump()值中可以看到after Testing(54,65,73,74,69,6e,67)之前和之后的空格和破折号(20,2d)c2,a0,即UTF-8多字节非破坏空格字符.(在Word文档中复制的文本中,您经常会看到与引号和其他非ASCII范围字符一起使用的卷曲引号和其他非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.
Run Code Online (Sandbox Code Playgroud)

或者用单字节等价物替换任何意外的多字节字符,如果可能的话,对你的数据有意义; 在这种情况下,正常空间可能会起作用,但是如果有任何替换,则会破坏可能实际上非常重要的信息.