|
--校验存储....
--简意:类型为VARCHAR2的字段, LENGTHB(字段的最大值)*1.5是否超过VARCHAR2(N)中的N,若超过,将更改表结构ALTER ..
CREATE OR REPLACE PROCEDURE CHANGE_VARCHAR2(USERNAME VARCHAR2 ) IS
--USERNAME 传入要判断的用户
P_OWNER VARCHAR2 (4000 );
P_TABLE_NAME VARCHAR2 (4000 );
P_COLUMN_NAME VARCHAR2 (4000 );
P_DATA_LENGTH NUMBER (30 );
P_SQL VARCHAR2 (4000 );
MAX_NUM NUMBER (20 ); ---要是写成VARCHAR2(2000),发现他没有比对,只是将只改成最大,其实就是跳过了比对
P_SQL_SQL VARCHAR2 (4000 );
--创建游标(包含:TABLE_NAME, COLUMN_NAME, DATA_LENGTH)
CURSOR C_CONS IS
SELECT OWNER, TABLE_NAME, COLUMN_NAME, DATA_LENGTH
FROM DBA_TAB_COLUMNS UTC
WHERE UTC.OWNER = UPPER (USERNAME)
AND UTC.DATA_TYPE = 'VARCHAR2'
AND UTC.TABLE_NAME NOT IN
( SELECT TABLE_NAME
FROM DBA_EXTERNAL_TABLES E
WHERE E.OWNER = UPPER (USERNAME)) --筛选掉临时表
AND UTC.TABLE_NAME NOT LIKE 'BIN%' ; --筛选掉回收站表
-- 编辑存储的用户要有查询DBA_TAB_COLUMNS/DBA_EXTERNAL_TABLES权限;
-- 没权限会报错:’ERROR: PL/SQL: ORA-00942: 表或视图不存在’
-- 或者用USER_TAB_COLUMNS/USER_EXTERNAL_TABLES视图避免权限问题..
-- 授权命令:GRANT SELECT ON DBA_TAB_COLUMNS TO 用户;
-- 授权命令:GRANT SELECT ON DBA_EXTERNAL_TABLES TO 用户;
BEGIN
FOR P_C_CONS IN C_CONS LOOP
P_OWNER := P_C_CONS.OWNER;
P_TABLE_NAME := P_C_CONS.TABLE_NAME;
P_COLUMN_NAME := P_C_CONS.COLUMN_NAME;
P_DATA_LENGTH := P_C_CONS.DATA_LENGTH;
P_SQL := 'SELECT ROUND((CASE WHEN NVL((MAX(LENGTHB(' ||
P_COLUMN_NAME || ')' ||
')*1.5 ),0) =0 THEN 1 ELSE (MAX(LENGTHB(' ||
P_COLUMN_NAME || ')' || ')*1.5 ) END)) FROM ' ||
P_OWNER || '.' || P_TABLE_NAME || ' WHERE LENGTH(' ||
P_COLUMN_NAME || ')!=LENGTHB(' || P_COLUMN_NAME || ')' ; --查询LENGTHB(字段的最大值)*1.5
--CASE WHEN 加判断是因为 字段可能存在空数据 (报错信息:ORA-06535: EXECUTE IMMEDIATE 中的语句字符串为 NULL 或长度为零)
--ROUND 若字段存的数据都是NUMBER 且都为1个数字,上面的SQL会为 将列改为1.5(报错:DATA TYPE INCORRECT) 所以四舍五入下..
--DBMS_OUTPUT.PUT_LINE(P_SQL); -- 若出现问题,打印信息,利于检验为题
EXECUTE IMMEDIATE P_SQL
INTO MAX_NUM;
--DBMS_OUTPUT.PUT_LINE(MAX_NUM);
IF MAX_NUM > P_DATA_LENGTH /*OR MAX_NUM = P_DATA_LENGTH*/
--如果LENGTHB(字段的最大值)*1.5的结果 大于 VARCHAR2(N)中的N ,执行alter table改字段长度到(LENGTHB(字段的最大值)*1.5)
THEN
P_SQL_SQL := 'ALTER TABLE ' || P_TABLE_NAME || ' MODIFY(' ||
P_COLUMN_NAME || ' VARCHAR2(' || MAX_NUM || ')) ' ;
--DBMS_OUTPUT.PUT_LINE(P_SQL_SQL); -- 若出现问题,打印信息,利于检验为题
EXECUTE IMMEDIATE P_SQL_SQL;
ELSE
RETURN ;
END IF ;
END LOOP ;
END CHANGE_VARCHAR2;
--使用步骤:
-- 编辑存储..-->调用存储(Call change_varchar2(username => 'u1' );或者begin...等)
|
|
大家是否有疑问,为什么只判断varchar2 不判断char 和nvarchar等类型么?
实验 :--字符集编码'GBK' 库中 字段类型为CHAR/NVARCHAR2导入到字符集编码'UTF-8'情况 :
SQL > SELECT USERENV( 'LANGUAGE' ) FROM DUAL;
USERENV ('LANGUAGE' )
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
SQL > CREATE TABLE T_1(CHA CHAR ( 2 ),NVARCHAR NVARCHAR2 ( 3 ));
Table created
SQL > INSERT INTO T_1 (CHA, NVARCHAR) VALUES ( '11' , '111' );
1 row inserted
SQL > INSERT INTO T_1 (CHA, NVARCHAR) VALUES ( 'AA' , '111' );
1 row inserted
SQL > INSERT INTO T_1 (CHA, NVARCHAR) VALUES ( '中' , '中中中' );
1 row inserted
SQL > commit ;
Commit complete
SQL > SELECT * FROM t_1;
CHA NVARCHAR
--- --------
11 111
AA 111
中 中中中
SQL >
--再在字符集编码'UTF-8'情况
SQL > SELECT USERENV( 'LANGUAGE' ) FROM DUAL;
USERENV ('LANGUAGE' )
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.AL32UTF8
SQL > create table T_1 as select * from sys.T_1@DB_GBK;
Table created
SQL > SELECT * FROM t_1;
CHA NVARCHAR
------ --------
11 111
AA 111
中 中中中
SQL >
|
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/781883/viewspace-1411259/ ,如需转载,请注明出处,否则将追究法律责任。