oracle使用imp导入报错ORA-12899

一个做审计的朋友从客户那里拿到了一个dmp文件,想让我帮他导入到数据库中便于查询数据,因为他电脑的oracle数据库也是找我帮他安装的,想着不过是举手之劳,所以我就欣然地答应了。

一、错误描述

说干就干,打开cmd窗口,执行imp命令开始导入,结果不断报错,信息如下:

1
2
3
IMP-00019: 由于 ORACLE 错误 12899 而拒绝行
IMP-00003: 遇到 ORACLE 错误 12899
ORA-12899: 列 "SALE"."XXXX_2021_2023"."是否高值" 的值太大 (实际值: 3, 最大值: 2)

二、原因分析

查看ORA-12899这个报错的原因:

1
2
3
4
5
6
7
8
9
10
11
12
12899, 00000, "value too large for column %s (actual: %s, maximum: %s)"
// *Cause: An attempt was made to insert or update a column with a value
// which is too wide for the width of the destination column.
// The name of the column is given, along with the actual width
// of the value, and the maximum allowed width of the column.
// Note that widths are reported in characters if character length
// semantics are in effect for the column, otherwise widths are
// reported in bytes.
// *Action: Examine the SQL statement for correctness. Check source
// and destination column data types.
// Either make the destination column wider, or use a subset
// of the source column (i.e. use substring).

虽然不清楚源数据的环境,但是结合数据正式导入前的提示,初步判断为数据库字符集差异导致

1
2
已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
导入服务器使用 AL32UTF8 字符集 (可能的字符集转换)

一个中文在字符集为AL32UTF8的数据库环境下占用3个字节,而字符集为ZHS16GBK时只占用2个字节,也就是说需要修改目标数据库的字符集与源数据库保持一致。

三、问题解决

经过以上的分析,知道问题出在数据库字符集上,那么接下来就开始修改数据库字符集:

3.1 查询数据库字符集

可通过下列几个SQL语句来查询当前数据库的字符集

1
2
3
SQL> SELECT * FROM V$NLS_PARAMETERS;
SQL> select * from sys.props$;
SQL> select * from NLS_DATABASE_PARAMETERS;
3.1 修改数据库字符集
1
2
3
4
5
6
7
8
9
SQL> shutdown immediate
SQL> startup mount;
SQL> alter system enable restricted session;
SQL> alter system set job_queue_processes=0;
SQL> alter system set aq_tm_processes=0;
SQL> alter database open;
SQL> alter database character set ZHS16GBK;
ERROR at line 1:
ORA-12712: new character set must be a superset of old character set

提示字符集不兼容,此时使用INTERNAL_USE参数来跳过字符集关系检测。

1
2
3
SQL> alter database character set INTERNAL_USE ZHS16GBK;
SQL> shutdown immediate
SQL> startup

至此,ORA-12899问题已经解决,数据也可以正常导入数据库了