因达梦数据库 新版本取消了 length_in_char 参数,老版本做dexp/dimp数据迁移时,会出现"string trunc" 的报错,影响数据完整性;

因为 length_in_char 参数主要是影响 varchar 、 varchar2 类型,故可以在数据库中查询到varchar 类型,并扩大对应的字段精度。

----查询所有的varchar 类型

select * from DBA_TAB_COLUMNS where owner='ANONYMOUS' and data_type ='VARCHAR' ;

–把ANONYMOUS用户下所有字段是varchar类型长度全部扩大3倍

declare
    CURSOR cur is
        select
            *
        from
            DBA_TAB_COLUMNS
        where
            owner = 'ANONYMOUS'
            and data_type = 'VARCHAR';
begin
    for i in cur LOOP
        execute immediate 'alter table ' || i.owner || '.' || i.table_name || ' modify ' || i.column_name || ' varchar(' || 3 * i.data_length || ');';
    end loop;
end;

可能出现的报错:
1、-2865:不能修改或删除聚集索引的列
2、-6121:数据精度超出范围
3、-3242:表中不能同时包含聚集 KEY 和大字段
4、-2528:物化视图和日志表不支持当前操作

聚集主键可以通过两个方式处理 :
            ① 将达梦的 PK_WITH_CLUSTER 参数改为 0 ,重新导入表结构创建表;但是当源库的DDL用的是聚集主键时,仍无法处理该报错;
            ② 将导出的dmp文件导入表结构到本地达梦库,通过dts的导入已修改为非聚集主键,且字段精度已扩大4倍的表结构SQL脚本;执行新的DDL sql脚本后,再通过dmp文件导入数据
                 DATA_ONLY = Y  --只导入表数据
            ③ 过滤主键字段,不做修改;使用如下语句进行修改除主键外的所有varchar字段;可将下述两种方式结合起来,既扩大字段精度,也修改存储方式 ;2 * varchar n char
                该方式可能出现,“数据精度超出范围”的报错,下述语句中提供部分解决方案

----将除主键外的所有varchar字段精度扩大3倍(不推荐)

declare
    CURSOR cur is
        select
            *
        from
            DBA_TAB_COLUMNS
        where
            owner = 'ANONYMOUS'
            and data_type = 'VARCHAR'
            and column_name not in (SELECT DISTINCT
                                        (ALL_CONS_COLUMNS.column_name)
                                    FROM
                                        SYSCONS,
                                        SYSOBJECTS,
                                        ALL_CONS_COLUMNS
                                    WHERE
                                        SYSCONS.id = SYSOBJECTS.id
                                        AND SYSCONS.TYPE$ = 'P'
                                        AND SYSOBJECTS.name = ALL_CONS_COLUMNS.CONSTRAINT_NAME
                                        AND ALL_CONS_COLUMNS.OWNER = 'ANONYMOUS');
begin
    for i in cur LOOP
        execute immediate 'alter table
    ' || i.owner || '.' || i.table_name || ' modify
' || i.column_name || ' varchar(' || 3 * i.data_length || ');';
    end loop;
end;

----将除主键外的所有varchar字段修改为varchar(n char) 的表达方式 (推荐该方式)

declare
    CURSOR cur is
        select
            *
        from
            DBA_TAB_COLUMNS
        where
            owner = 'ANONYMOUS'
            and data_type = 'VARCHAR'
            and column_name not in (SELECT DISTINCT
                                        (ALL_CONS_COLUMNS.column_name)
                                    FROM
                                        SYSCONS,
                                        SYSOBJECTS,
                                        ALL_CONS_COLUMNS
                                    WHERE
                                        SYSCONS.id = SYSOBJECTS.id
                                        AND SYSCONS.TYPE$ = 'P'
                                        AND SYSOBJECTS.name = ALL_CONS_COLUMNS.CONSTRAINT_NAME
                                        AND ALL_CONS_COLUMNS.OWNER = 'ANONYMOUS');
begin
    for i in cur LOOP
        execute immediate 'alter table
' || i.owner || '.' || i.table_name || ' modify
' || i.column_name || ' varchar(' || i.data_length || ' char);';
    end loop;

----- -6121: 数据精度超出范围
-----varchar字段粗暴的扩大3倍的方式,varchar字段精度可能会超出范围,此时可以通过以下语句,将varchar精度超过10000的字段修改为大字段clob;
-----该方式仅能解决非聚集主键的表数据导入
-----聚集主键会报错 “不能同时包含聚集KEY和大字段”

declare
    CURSOR cur is
        select
            *
        from
            DBA_TAB_COLUMNS
        where
            owner = 'ANONYMOUS'
            and data_type = 'VARCHAR'
            and data_length > 10000;
begin
    for i in cur LOOP
        execute immediate 'alter table
' || i.owner || '.' || i.table_name || ' add column
(' || i.column_name || '_2 clob)';
        execute immediate 'alter table
' || i.owner || '.' || i.table_name || ' drop column
' || i.column_name;
        execute immediate 'alter table
' || i.owner || '.' || i.table_name || ' rename column
' || i.column_name || '_2 to ' || i.column_name;
    end loop;
end;

--------[-2528]:物化视图和日志表不支持当前操作
--------可通过以下方式绕过: (除去物化视图与物化视图日志表)

declare
    CURSOR cur is
        select * from DBA_TAB_COLUMNS where owner='ANONYMOUS' and data_type ='VARCHAR'
and table_name in (select table_name from dba_tables  where owner='ANONYMOUS' and table_name not like 'MTAB$%') ;
begin
    for i in cur LOOP
        execute immediate 'alter table ' || i.owner || '.' || i.table_name || ' modify ' || i.column_name || ' varchar(' || 3 * i.data_length || ');';
        print ( i.owner || '.' || i.table_name ||' 表中的 ' ||i.column_name ||' 字段已修改');
    end loop;
end;
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐