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)
您将看到字符和字节长度语义之间的区别:
您必须为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)
或者用单字节等价物替换任何意外的多字节字符,如果可能的话,对你的数据有意义; 在这种情况下,正常空间可能会起作用,但是如果有任何替换,则会破坏可能实际上非常重要的信息.