代码改变世界

CSSCAN 输出的处理

2021-05-26 20:41  那个,我  阅读(283)  评论(0编辑  收藏  举报

1.背景知识


有些情况下我们需要跨字符集进行表的迁移
比如 ZHS16GBK->AL32UTF8
在存储中文时两个字符集有如下差异

字符集 中文字符占用字节 以汉字存储性别
ZHS16GBK 2 char(2)
AL32UTF8 3 char(3)
那么当把一个包含字段 char(2),varchar2(10) 的表从ZHS16GBK 迁移到 AL32UTF8 时,可能就会遇到字段长度不足的报错。
这时就要用到 csscan 工具,该工具oracle 自带,位于$ORACLE_HOME/bin 目录

csscan 用法示例:

基于用户:
csscan userid=cym/cym user=cym tochar=AL32UTF8 ARRAY=20480000 process=4 SUPPRESS=0

基于表:
csscan userid=cym/cym table=cym.cym1,cym.cym2 tochar=AL32UTF8 ARRAY=20480000 process=4 SUPPRESS=0

  • process 并行数
  • suppress 不记录迁移失败的数据行

扫描结果包含3个文件:
scan.err scan.out scan.txt

scan.err 包含了要处理的表字段及变更放法,如果要变更的字段很多,这个文件会很大,人工处理耗时耗力且可能遗漏。于是就想要写个脚本实现对 scan.err 文件的处理。

csprocess.sh

#!/bin/bash
############################################
# csprocess.sh
# 用途说明:
#    用来处理 csscan 得到的 .err 文件
# 用法示例: 
#    sh csprocess.sh scan.err
#

if [ ! $1 ];then
    file=scan.err
else
    file=$1
fi

i=1

grep ':' $file | grep -E '^User|^Table|^Column|^Type|^Max' | awk -F ':' '{print $2}' | while read line
do
    if [ $i -eq 1 ];then
        v1='ALTER TABLE '$line
    elif [ $i -eq 2 ];then
        v2='.'$line
    elif [ $i -eq 3 ];then
        v3=' MODIFY '$line' '
    elif [ $i -eq 4 ];then
        v4=`echo $line|awk -F '(' '{print $1}'`
    elif [ $i -eq 5 ];then
        echo $v1$v2$v3$v4'('$line');' >> cs.sql
        i=0
    fi
    ((i++))
done

2.测试演示


  1. 建表
create table cym1(id number,gender char(2),mark varchar2(10));
create table cym2(id number,gender char(6),mark varchar2(10));
create table cym3(id number,gender char(2),mark varchar2(16));
insert into cym1 values(1111,'男','我爱你中国');
insert into cym2 values(1111,'male','IloveChina');
insert into cym3 values(1111,'男','我爱你中国');
commit;
  1. csscan 扫描
[oracle@BServer007 test]$ csscan userid=cym/cym table=cym.cym1,cym.cym2,cym.cym3 tochar=AL32UTF8 ARRAY=20480000 process=4 SUPPRESS=0
[oracle@BServer007 test]$ ls
csprocess.sh  scan.err  scan.out  scan.txt
  1. 获取变更SQL
[oracle@BServer007 test]$ sh csprocess.sh 
[oracle@BServer007 test]$ ls
csprocess.sh  cs.sql  scan.err  scan.out  scan.txt
[oracle@BServer007 test]$ cat cs.sql 
ALTER TABLE CYM.CYM1 MODIFY MARK VARCHAR2(15);
ALTER TABLE CYM.CYM3 MODIFY GENDER CHAR(3);
ALTER TABLE CYM.CYM1 MODIFY GENDER CHAR(3);

数据迁移方案推荐


  1. 调整原库的表字段长度。(不推荐)
  2. 先迁移元数据,目标端根据获得的脚本调整完字段后再单独迁移数据。(推荐)

补充:case 写法

经测试,效率上两种写法基本无差异

#!/bin/bash
############################################
# csprocess.sh
# 说明:
#    用来处理 csscan 得到的.err 文件
# 用法示例: 
#    sh csprocess.sh scan.err
#

if [ ! $1 ];then
    file=scan.err
else
    file=$1
fi

i=1

grep ':' $file | grep -E '^User|^Table|^Column|^Type|^Max' | awk -F ':' '{print $2}' | while read line
do
    case $i in
        1)  v1='ALTER TABLE '$line ;;
        2)  v2='.'$line ;;
        3)  v3=' MODIFY '$line' ' ;;
        4)  v4=`echo $line|awk -F '(' '{print $1}'` ;;
        5)  echo $v1$v2$v3$v4'('$line');' >> cs.sql;
            i=0 ;;
    esac
    ((i++))
done