共计 3579 个字符,预计需要花费 9 分钟才能阅读完成。
作者:杨文
DBA,负责客户我的项目的需要与保护,会点数据库,不限于 MySQL、Redis、Cassandra、GreenPlum、ClickHouse、Elastic、TDSQL 等等。
本文起源:原创投稿
* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
1、问题形容
有时咱们在导入导出数据时,须要对数据进行解决,来满足业务上的数据需要,此时须要应用管制文件配合导数工具来满足业务上不同数据的需要。
2、管制文件模板:
lang=java(列名 字节偏移地位 ( 可选) "预处理函数" 映射定义 (可选),
列名 字节偏移地位 (可选) "预处理函数" 映射定义 (可选),
列名 字节偏移地位 (可选) "预处理函数" 映射定义 (可选)
);
简略示例:
lang=java
server=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.dat
1@##oceanbase@##2023-01-12 15:00:00.0@##1@##ob@##1@##ob
2@##oceanbase@##2023-01-12 15:00:00.0@##2@##ob@##2@##ob
3@##oceanbase@##2023-01-12 15:00:00.0@##3@##ob@##3@##ob
create 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.ctl
lang=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.ctl
lang=java(id "none" map(1)
);
导入数据,能够看到报错信息:
Error:"Field'id'doesn't have a default value"
批改管制文件:
vi /data/test01.ctl
lang=java(id "none" map(1),
name "none" map(2)
);
此时再导入是胜利的。
阐明:
- 插入局部列时,须要为插入的每列,在参数文件中指定对应的文本列。
- not null 列必须有对应的插入数据,或者是有缺省值。
3.4、案例 3:
表列多于文本列:全列导入。
管制文件:
vi /data/test02.ctl
lang=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.ctl
lang=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)
小倡议:
数据导入后进行简略查看每个字段导入的数据是否是对应的。可能存在某些状况下数据导入了,但理论数据和字段并没有对齐,可能只是凑巧数据能存入对应字段。以及查看中文是否失常显示。