注册
length_in_char参数值不同库之前的数据迁移
专栏/培训园地/ 文章详情 /

length_in_char参数值不同库之前的数据迁移

啦啦啦 2024/04/24 2319 2 0
摘要

LENGTH_IN_CHAR参数解析

1、属性

初始化参数,初始化完成后不可修改

2、含义

VARCHAR 类型对象的长度是否以字符为单位。

3、取值范围

Y 表示是,0、N 表示否。缺省值为 0。
(1)1 或 Y:是,所有 VARCHAR 类型对象的长度以字符为单位。这种情况下,定义长度并非真正按照字符长度调整,而是将存储长度值按照理论字符长度进行放大。所以会出现实际可插入字符数超过定义长度的情况,这种情况也是允许的。同时,存储的字节长度 32767 上限仍然不变,也就是说,即使定义列长度为32767 字符,其实际能插入的字符串占用总字节长度仍然不能超过 32767;
(2)0 或 N:否,所有 VARCHAR 类型对象的长度以字节为单位。

4、查看当前取值

以下几种方法均可
(1) SELECT SF_GET_LENGTH_IN_CHAR();
(2) SELECT VALUE FROM V$PARAMETER WHERE NAME='LENGTH_IN_CHAR';
(3)管理工具右击数据库连接,选中管理服务器功能栏查看。

需求目标

将LENGTH_IN_CHAR为0库中的数据迁移至为1的库时,可无异常迁移。

将LENGTH_IN_CHAR为1库中的数据迁移至为0的库时,使用逻辑迁移工具,经常会遇到数据超长的异常,如果迁移的表列很多的话,这个异常会很困扰,一个个处理很费时费力,于是尝试编写一个SQL过程进行预检查。

解决方案

编写一个SQL块,循环检索指定范围内每个varchar类型列的最长值的字节数,并与定义长度比较,有超出就记录。
再选择是在源端进行提前放大,或是先迁移表ddl至目标端,在目标端放大后再进行数据迁移导入。
需要提前按需修改语句中owner和table_name的值

打印模式

--按需修改owner和table_name的值
----length_in_char为1的库,往为0的库迁移超长截断预查询
DECLARE
max_length number;
LENGTH_SQL VARCHAR;
length_record varchar;
BEGIN
  FOR col IN (SELECT owner,table_name,column_name,data_length FROM all_tab_columns WHERE data_type like 'VARCHAR%' and 
--按需修改owner和table_name的值
owner='TEST_USER' and 
table_name='TEST_TABLE')
  LOOP
  
    LENGTH_SQL := 'SELECT MAX(LENGTHB("' || col.column_name || '")) FROM "' || col.owner||'"."'||col.table_name||'"';
    EXECUTE IMMEDIATE LENGTH_SQL INTO max_length;
    --DBMS_OUTPUT.PUT_LINE(' ');
    
    IF max_length > col.data_length THEN
        length_record := 'Owner: ' || col.owner || ', Table: ' || col.table_name || ', Column: ' || col.column_name || ', Curr Max Length: ' || max_length ||', Declare Data Length: '||col.data_length;
         DBMS_OUTPUT.PUT_LINE(length_record);
     --INSERT INTO exceeded_columns (username, table_name, column_name, curr_max_length, declare_data_length) VALUES (col.owner, col.table_name, col.column_name,max_length,col.data_length);
      
    END IF;
  END LOOP;
  
  COMMIT; 
END;
/

image.png

记录表模式

创建记录表

CREATE TABLE exceeded_columns (
  username VARCHAR2(100),
  table_name VARCHAR2(100),
  column_name VARCHAR2(100),
  curr_max_length int,
  declare_data_length int
);
--按需修改owner和table_name的值
----length_in_char为1的库,往为0的库迁移超长截断预查询
DECLARE
max_length number;
LENGTH_SQL VARCHAR;
length_record varchar;
BEGIN
  FOR col IN (SELECT owner,table_name,column_name,data_length FROM all_tab_columns WHERE data_type like 'VARCHAR%' and 
--按需修改owner和table_name的值
owner='TEST_USER' and 
table_name='TEST_TABLE')
  LOOP
  
    LENGTH_SQL := 'SELECT MAX(LENGTHB("' || col.column_name || '")) FROM "' || col.owner||'"."'||col.table_name||'"';
    EXECUTE IMMEDIATE LENGTH_SQL INTO max_length;
    --DBMS_OUTPUT.PUT_LINE(' ');
    
    IF max_length > col.data_length THEN
        length_record := 'Owner: ' || col.owner || ', Table: ' || col.table_name || ', Column: ' || col.column_name || ', Curr Max Length: ' || max_length ||', Declare Data Length: '||col.data_length;
         --DBMS_OUTPUT.PUT_LINE(length_record);
     INSERT INTO exceeded_columns (username, table_name, column_name, curr_max_length, declare_data_length) VALUES (col.owner, col.table_name, col.column_name,max_length,col.data_length);
      
    END IF;
  END LOOP;
  
  COMMIT; 
END;
/

image.png

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服