SQL Loader - 实际长度超过最大值

时间:2017-03-03 10:23:48

标签: sql oracle sql-loader

我尝试使用sql loader将数据加载到表中。

日志显示字符串的实际长度为101,其中100为最大值(拒绝记录)。但是当我选中时,我发现长度为99.

字符串的数据类型是表

中的varchar2(100)

我没有在控制文件中指定任何有关长度的内容

究竟会出现什么问题?

1 个答案:

答案 0 :(得分:3)

您的数据值只有99个字符,但有些似乎是multibyte characters - 评论中至少有一个是½符号。

有两种相关的方法可以查看此行为,具体取决于您的表的定义方式以及控制文件中的内容。

您可能会看到character length semantics的影响。您的列定义为100 bytes ;您尝试插入99个字符,但由于某些字符需要多个字节进行存储,因此字符串所需的字节总数为101 - 对于列定义来说太多了。

你可以在这里看到这种效果:

create table t42 (str varchar2(10 byte));

然后,如果我有一个具有多字节字符的行的数据文件:

This is 10
This is 9½

和一个简单的控制文件:

LOAD DATA
CHARACTERSET UTF8
TRUNCATE INTO TABLE T42
FIELDS TERMINATED BY ','
TRAILING NULLCOLS
(
  STR
)

然后尝试加载它:

Record 2: Rejected - Error on table T42, column STR.
ORA-12899: value too large for column "MYSCHEMA"."T42"."STR" (actual: 11, maximum: 10)

Total logical records read:             2
Total logical records rejected:         1

如果我用字符语义重新创建表:

drop table t42 purge; 创建表t42(str varchar2(10 char));

然后加载相同的数据和控制文件现在没有错误,并且:

Total logical records read:             2
Total logical records rejected:         0

但是,即使用字符语义定义表,你仍然可以看到这个;如果我删除行CHARACTERSET UTF8,那么我的环境默认值(通过NLS_LANG,恰好将我的字符集设置为WE8ISO8859P1)会导致字符集不匹配,我再次看到:

Record 2: Rejected - Error on table T42, column STR.
ORA-12899: value too large for column "STACKOVERFLOW"."T42"."STR" (actual: 11, maximum: 10)

(如果没有该控制文件行,并且该列具有字节语义,则错误报告的实际长度为13而不是11)。

因此,您需要定义表以保存您期望的字符的最大数量,如果您的NLS_LANG是,则需要控制文件来指定字符集将其默认为与数据库字符集不匹配的内容。

您可以通过查询,数据库默认值和当前会话默认值来查看新表将获得的默认语义:

select value from nls_database_parameters where parameter = 'NLS_LENGTH_SEMANTICS';
select value from nls_session_parameters where parameter = 'NLS_LENGTH_SEMANTICS';

对于现有表,您可以通过查看user_tab_columns.char_used列来检查使用哪个表,对于字节语义,B将是B,对于字符语义,C将是C.