作者:杨文
DBA,负责客户我的项目的需要与保护,会点数据库,不限于MySQL、Redis、Cassandra、GreenPlum、ClickHouse、Elastic、TDSQL等等。
本文起源:原创投稿
*爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
1、问题形容
有时咱们在导入导出数据时,须要对数据进行解决,来满足业务上的数据需要,此时须要应用管制文件配合导数工具来满足业务上不同数据的需要。
2、管制文件模板:
lang=java( 列名 字节偏移地位(可选) "预处理函数" 映射定义(可选), 列名 字节偏移地位(可选) "预处理函数" 映射定义(可选), 列名 字节偏移地位(可选) "预处理函数" 映射定义(可选));
简略示例:
lang=javaserver=mysql/oracle( c1 "nvl(c1,'not null')" map(field_position), c2 "none" map(field_position));
参数阐明:
- field_position为导入的数据文件中预处理数据的列地位。
- 管制文件的命名标准:table_name.ctl,大小写与数据库中保持一致。
- 管制文件的内容要求列名的程序与表中定义的列程序保持一致,且列名大小写与表中的列名大小写保持一致。
3、应用案例:
3.1、测试数据:
cat /data/test/TABLE/test.dat1@##oceanbase@##2023-01-12 15:00:00.0@##1@##ob@##1@##ob2@##oceanbase@##2023-01-12 15:00:00.0@##2@##ob@##2@##ob3@##oceanbase@##2023-01-12 15:00:00.0@##3@##ob@##3@##obcreate table test01 (id int(10) not null primary key,name varchar(10),time timestamp not null default '1971-01-01 01:01:01',blank varchar(255) null);create table test02 (id int(10) not null primary key,name varchar(10) not null,time timestamp not null,bar varchar(255) default null,blank varchar(255) default null,line varchar(255) default null,mark varchar(255) default null,test varchar(255) not null);
3.2、案例1:
表列少于文本列:表全列导入。
管制文件:
vi /data/test01.ctllang=java(id "none" map(1),name "none" map(2),time "none" map(3),blank "none" map(5));
导入语句:
./obloader -h 10.186.60.94 -P 2883 -u root -p rootroot \-c ywob -t mysql_yw_tent -D ywdb --table test01 --cut \-f /data/test/TABLE/test.dat --log-path /data/ --external-data \--replace-data --column-splitter '@##' --ctl-path /data/test01.ctl
输入后果:
All Dump Tasks Finished:---------------------------------------------------------------------------------------------------- No.# | Type | Name | Count | Status---------------------------------------------------------------------------------------------------- 1 | TABLE | test01 | 3 | SUCCESS-------------------------------------------------------------------------
能够看到是胜利的。此时,咱们进库再进行select查问数据进行验证,能够看到确实是胜利的。
3.3、案例2:
表列少于文本列:表局部列导入。
管制文件:
vi /data/test01.ctllang=java(id "none" map(1));
导入数据,能够看到报错信息:
Error:"Field 'id' doesn't have a default value"
批改管制文件:
vi /data/test01.ctllang=java(id "none" map(1),name "none" map(2));
此时再导入是胜利的。
阐明:
- 插入局部列时,须要为插入的每列,在参数文件中指定对应的文本列。
- not null列必须有对应的插入数据,或者是有缺省值。
3.4、案例3:
表列多于文本列:全列导入。
管制文件:
vi /data/test02.ctllang=java(id "none" map(1),name "none" map(2),time "none" map(3),bar "none" map(4),blank "none" map(5),line "none" map(6),mark "none" map(7));
导入语句:
./obloader -h 10.186.60.94 -P 2883 -u root -p rootroot \-c ywce -t mysql_yw_tent -D ywdb --table test02 --cut \-f /data/test/TABLE/test.dat --log-path /data/ --external-data \--replace-data --column-splitter '@##' --ctl-path /data/test02.ctl
输入后果:
All Dump Tasks Finished:---------------------------------------------------------------------------------------------------- No.# | Type | Name | Count | Status---------------------------------------------------------------------------------------------------- 1 | TABLE | test02 | 3 | SUCCESS----------------------------------------------------------------------------------------------------
能够看到是胜利的。然而明天在另一个同版本的OB环境下意外的发现了一个怪事,居然报错了:
Error: Column count doesn't match value count at row 1
报错信息:列数不匹配。
依据这种状况进行剖析:发现JDK版本不统一。并且能够看到导入的数据文件比表构造少一列,数据文件以“@##”作为列分隔符,并且最初一列结尾没有分隔符。
解决:
形式1:批改管制文件:
vi /data/test02.ctllang=java(id "none" map(1),name "none" map(2),time "none" map(3),bar "none" map(4),blank "none" map(5),line "none" map(6),mark "none" map(7),test "none" map(1));
形式2:批改表构造,最初一个字段能够为null。
形式3:批改数据文件,在最初面增加‘@##’后缀。
3.5、在应用“obdumper+管制文件”导出数据时,也有可能会呈现该报错信息:
Error: Column count doesn't match value count at row 1
可能的起因:数据库名大小写敏感,即数据库中的库名是小写,然而导出命令中写成了大写,导致管制文件中的配置内容不失效。
补充:
其实,还能够应用SUBSTR(char,position[,length ])进行截取解决数据;
示例:
SUBSTR('abc',0,3)
小倡议:
数据导入后进行简略查看每个字段导入的数据是否是对应的。可能存在某些状况下数据导入了,但理论数据和字段并没有对齐,可能只是凑巧数据能存入对应字段。以及查看中文是否失常显示。