在某个项目之中,由于相关业务调整,客户需要更新数据库中的部分编码。但是编码并不是一个编码存放在一个字段之中,而是在一个字段之中存放多个编码,编码之间使用","分隔,且字段内编码数量不固定,如下所示:
COL
001,002,003
01,001,0011
006
007,008,009,010
这样的编码字段存在于多个表之中,替换存在一定难度。
新旧编码存在对应关系,且为一一对应。但
因为新旧编码一一对应,所以考虑使用嵌套replace的方式更新字段
UPDATE TB SET COL = REPLACE(COL,'旧编码','新编码')
此方法存在问题,由于旧编码之间存在包含关系,可能在更新01的时候,更新了001的内容,所以需要精准识别每一个独立的编码。
如下:
UPDATE TB SET COL = REPLACE(COL,',旧编码,',',新编码,')
因为使用","作为字符串内编码之间的分隔符,所以两个","之间的编码可视为独立编码,但字符串的第一个编码与最后一个编码无法被识别,需要单独使用substing_index进行拆分后再次进行replace更新后再concat连接后再进行update操作。
但是仍然存在问题,因为新旧编码之间存在相同值,而嵌套replace是每次更新对所有值都生效,但是没办法判断编码为新编码还是旧编码,可能存在,旧编码的001对应新编码的03,旧编码的03对应新编码的005,replace更新完001为03后,有被更新为005这样的情况。
所以,不能使用replace的方式更新。
将字符串按照","进行分割,分割为单独的编码,分割后使用新旧编码对应表进行匹配更新,更新后再使用concat连接,完成更新。
难点在于:
首先使用REGEXP_COUNT函数判断找出表中最长的编码字符串,使用这个最大编码数量对字段进行拆分,
使用REGEXP_SUBSTR函数进行拆分字段,将源表只保留主键与需要切割的字段,使用循环进行拼接建表语句与插入语句。完成后按列进行循环更新,更新完成后再次拼接,重组字段,再使用主键关联,更新原表数据。完成分割更新操作。
之后再创建配置表,将分割更新存储过程参数写入,使用游标循环执行,完成主控程序,实现循环多表更新操作。
readme
一、建表语句在存储过程之前创建
二、编码替换程序在主控程序之前创建
三、建表语句、编码替换程序以及主控程序需要在创建在用户的默认模式下
四、程序使用方法:
1、批量替换多张表:
1)使用前,先向 TB_BATCH_REPLACE 表内插入对应数据并提交
2)执行主控程序:
CALL SP_BATCH_REPLACE();
2、单独更新一张表:
1)执行编码替换程序:
CALL SP_REPLACE_KEY(P_IN_SCHEMA,P_IN_TABLE,P_IN_UNQ_COLUMN,P_IN_TAG_COLUMN,P_IN_KEY_SCHEMA,P_IN_KEY_MAP,P_IN_OLD_KEY_COLUMN,P_IN_NEW_KEY_COLUMN);
其中:
P_IN_SCHEMA 为需要替换的目标表所在的模式名
P_IN_TABLE 为需要替换的目标表的表名
P_IN_UNQ_COLUMN 为需要替换的目标表中的主键或唯一键,需要唯一
P_IN_TAG_COLUMN 为需要更新编码的字段,需要为字符类型,如果字段为组合字段,需要以英文逗号(,)分隔
P_IN_KEY_SCHEMA 为更新编码的对应的KEY表所在的模式名
P_IN_KEY_MAP 为更新编码的对应的KEY表表名
P_IN_OLD_KEY_COLUMN 为更新编码的对应的KEY表中,与目标表中编码匹配的旧编码
P_IN_NEW_KEY_COLUMN 为更新编码的对应的KEY表中,替换目标表中编码的新编码
KEY表中新旧编码需要一一对应
例如:
CALL SP_REPLACE_KEY('JYGLJ','BSYZ_ZSPJZM','ID','XFZMFL','JYGLJ','A_ZM_CODE','ZFW_CODE_KEY2','ZFW_CODE_KEY1');
五、表
1、批量替换表 TB_BATCH_REPLACE
表中字段分别为F_IN_SCHEMA,F_IN_TABLE,F_IN_UNQ_COLUMN,F_IN_TAG_COLUMN,F_IN_KEY_SCHEMA,F_IN_KEY_MAP,F_IN_OLD_KEY_COLUMN,F_IN_NEW_KEY_COLUMN
分别与编码替换程序的输入参数一一对应。
插入数据语句为:
INSERT INTO TB_BATCH_REPLACE(F_IN_SCHEMA,F_IN_TABLE,F_IN_UNQ_COLUMN,F_IN_TAG_COLUMN,F_IN_KEY_SCHEMA,F_IN_KEY_MAP,F_IN_OLD_KEY_COLUMN,F_IN_NEW_KEY_COLUMN)
VALUES ('TEST1','TEST2','TEST3','TEST4','TEST5','TEST6','TEST7','TEST8');
2、日志表 LOG_SP_RUN
其中:
ID 为自增列
IS_BATCH 为主控程序判断标志位,1为主控程序,0为非主控程序,默认为0
SP_NAME 为当前执行存储过程名
STATUS 为程序运行状态,0为正常,1为异常
SP_LOG_NUM 为每次执行存储过程内的小日志号
START_TIME 为本次执行存储过程的开始时间
CURR_TIME 为本条日志的写入时间
SP_PARA_VALUE 为本次存储过程的执行参数语句
REMARK 为本条日志的信息
使用方法:
再使用了存储过程后,查询日志表,查看执行情况
例如:
SELECT * FROM LOG_SP_RUN ORDER BY ID DESC;
建表语句
CREATE TABLE TB_BATCH_REPLACE
(F_IN_SCHEMA VARCHAR(400),
F_IN_TABLE VARCHAR(400),
F_IN_UNQ_COLUMN VARCHAR(400),
F_IN_TAG_COLUMN VARCHAR(400),
F_IN_KEY_SCHEMA VARCHAR(400),
F_IN_KEY_MAP VARCHAR(400),
F_IN_OLD_KEY_COLUMN VARCHAR(400),
F_IN_NEW_KEY_COLUMN VARCHAR(400));
CREATE TABLE LOG_SP_RUN
(ID INT IDENTITY(1,1) NOT NULL,
IS_BATCH INT DEFAULT 0,
SP_NAME VARCHAR(400),
STATUS INT DEFAULT 0,
SP_LOG_NUM INT,
START_TIME DATETIME,
CURR_TIME DATETIME,
SP_PARA_VALUE VARCHAR(800),
REMARK VARCHAR(4000));
编码替换
CREATE OR REPLACE PROCEDURE SP_REPLACE_KEY
(P_IN_SCHEMA IN VARCHAR,
P_IN_TABLE IN VARCHAR,
P_IN_UNQ_COLUMN IN VARCHAR,
P_IN_TAG_COLUMN IN VARCHAR,
P_IN_KEY_SCHEMA IN VARCHAR,
P_IN_KEY_MAP IN VARCHAR,
P_IN_OLD_KEY_COLUMN IN VARCHAR,
P_IN_NEW_KEY_COLUMN IN VARCHAR)
AS
V_LOG_NUM INT;
V_START_TIME TIMESTAMP(6);
V_PARA_VALUE VARCHAR(800);
V_SQL VARCHAR(1000);
V_IS_EXISTS INT;
V_CURR_USER VARCHAR(200);
V_IS_VAILD INT;
V_MAX_CNT INT;
V_CREATE_TB_SQL VARCHAR(4000);
V_INSERT_TB_SQL_I VARCHAR(4000);
V_INSERT_TB_SQL_V VARCHAR(4000);
V_INSERT_TB_SQL_RESULT VARCHAR(4000);
V_CONCAT_COL_SQL VARCHAR(4000);
BEGIN
/*初始化参数*/
SET V_LOG_NUM = 1;
SET V_START_TIME = NOW;
SET V_PARA_VALUE = 'SP_REPLACE_KEY('''||P_IN_SCHEMA||''','''||P_IN_TABLE||''','''||P_IN_UNQ_COLUMN||''','''||P_IN_TAG_COLUMN||''','''||P_IN_KEY_SCHEMA||''','''||P_IN_KEY_MAP||''','''||P_IN_OLD_KEY_COLUMN||''','''||P_IN_NEW_KEY_COLUMN||''')';
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'开始运行');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
/*判断部分*/
-- 判断目标表
-- 判断输入模式是否正确
SET V_SQL = 'SELECT COUNT(1) FROM ALL_OBJECTS WHERE OBJECT_TYPE = ''SCH'' AND OBJECT_NAME = '''||P_IN_SCHEMA||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——目标表判断——输入模式不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('该模式('||P_IN_SCHEMA||')不存在,请检查输入模式名是否正确');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——目标表判断——输入模式存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断用户是否有权限操作该模式对象
SELECT USER INTO V_CURR_USER;
SET V_SQL = 'SELECT COUNT(1) FROM ALL_OBJECTS WHERE OBJECT_TYPE = ''SCH'' AND OWNER = '''||V_CURR_USER||''' AND OBJECT_NAME = '''||P_IN_SCHEMA||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
SELECT COUNT(1) INTO V_IS_VAILD FROM SESSION_ROLES WHERE ROLE = 'DBA';
IF V_IS_EXISTS + V_IS_VAILD < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——目标表判断——用户权限不足');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('当前用户('||V_CURR_USER||')并非该模式('||P_IN_SCHEMA||')所有者,且无DBA权限,不能对该模式进行操作。请更换用户操作或检查输入模式名是否正确');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——目标表判断——用户权限判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断模式下需要修改的表格是否存在
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TABLES WHERE OWNER = '''||P_IN_SCHEMA||''' AND TABLE_NAME = '''||P_IN_TABLE||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——目标表判断——目标表不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('该模式('||P_IN_SCHEMA||')下,不存在此表('||P_IN_TABLE||')。请检查输入模式名与表名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——目标表判断——目标表存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断主键字段是否存在
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TAB_COLUMNS WHERE OWNER = '''||P_IN_SCHEMA||''' AND TABLE_NAME = '''||P_IN_TABLE||''' AND COLUMN_NAME = '''||P_IN_UNQ_COLUMN||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——字段判断——主键字段不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('该模式('||P_IN_SCHEMA||')的这张表('||P_IN_TABLE||')中不存在此字段('||P_IN_UNQ_COLUMN||')。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——字段判断——主键字段存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断主键字段是否唯一
SET V_SQL = 'SELECT COUNT(1)
FROM (
SELECT COUNT(DISTINCT '||P_IN_UNQ_COLUMN||') AS F_DIS_CNT,COUNT(1) AS F_CNT
FROM '||P_IN_SCHEMA||'.'||P_IN_TABLE||') T
WHERE T.F_DIS_CNT = T.F_CNT
AND T.F_CNT > 0';
EXECUTE IMMEDIATE V_SQL INTO V_IS_VAILD;
IF V_IS_VAILD < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——字段判断——主键字段值不唯一');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('该模式('||P_IN_SCHEMA||')的这张表('||P_IN_TABLE||')中的此字段('||P_IN_UNQ_COLUMN||')中的值不唯一。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——字段判断——主键字段唯一性判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断需要修改的字段是否存在
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TAB_COLUMNS WHERE OWNER = '''||P_IN_SCHEMA||''' AND TABLE_NAME = '''||P_IN_TABLE||''' AND COLUMN_NAME = '''||P_IN_TAG_COLUMN||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——字段判断——目标字段不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('该模式('||P_IN_SCHEMA||')的这张表('||P_IN_TABLE||')中不存在此字段('||P_IN_TAG_COLUMN||')。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——字段判断——目标字段存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断需要修改的字段类型是否正确
SET V_SQL = 'SELECT COUNT(1)
FROM ALL_TAB_COLUMNS
WHERE OWNER = '''||P_IN_SCHEMA||''' AND TABLE_NAME = '''||P_IN_TABLE||'''
AND DATA_TYPE IN (''CHAR'',''VARCHAR2'',''NVARCHAR2'')
AND COLUMN_NAME = '''||P_IN_TAG_COLUMN||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——字段判断——目标字段类型非字符类型');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('该模式('||P_IN_SCHEMA||')的这张表('||P_IN_TABLE||')中的此字段('||P_IN_TAG_COLUMN||')类型不为字符类型。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——字段判断——目标字段类型判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断KEY表
-- 判断输入的KEY表模式是否正确
SET V_SQL = 'SELECT COUNT(1) FROM ALL_OBJECTS WHERE OBJECT_TYPE = ''SCH'' AND OBJECT_NAME = '''||P_IN_KEY_SCHEMA||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——KEY表模式不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('输入的KEY表模式('||P_IN_KEY_SCHEMA||')不存在,请检查输入模式名是否正确');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——KEY判断——KEY表模式存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断用户是否有权限操作KEY表模式对象
SELECT USER INTO V_CURR_USER;
SET V_SQL = 'SELECT COUNT(1) FROM ALL_OBJECTS WHERE OBJECT_TYPE = ''SCH'' AND OWNER = '''||V_CURR_USER||''' AND OBJECT_NAME = '''||P_IN_KEY_SCHEMA||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
SELECT COUNT(1) INTO V_IS_VAILD FROM SESSION_ROLES WHERE ROLE = 'DBA';
IF V_IS_EXISTS + V_IS_VAILD < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——用户对KEY表模式权限不足');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('当前用户('||V_CURR_USER||')并非KEY表所在模式('||P_IN_KEY_SCHEMA||')所有者,且无DBA权限,不能对该模式进行操作。请更换用户操作或检查输入KEY表模式名是否正确');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——KEY判断——用户对KEY表模式权限判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断KEY表是否存在
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TABLES WHERE OWNER = '''||P_IN_KEY_SCHEMA||''' AND TABLE_NAME = '''||P_IN_KEY_MAP||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——KEY表不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('输入的KEY表模式('||P_IN_KEY_SCHEMA||')下,不存在KEY表('||P_IN_KEY_MAP||')。请检查输入模式名与表名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——KEY判断——KEY表存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断OLD字段是否存在
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TAB_COLUMNS WHERE OWNER = '''||P_IN_KEY_SCHEMA||''' AND TABLE_NAME = '''||P_IN_KEY_MAP||''' AND COLUMN_NAME = '''||P_IN_OLD_KEY_COLUMN||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——OLD字段不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('输入的KEY表模式('||P_IN_KEY_SCHEMA||')的KEY表('||P_IN_KEY_MAP||')中不存在OLD_KEY字段('||P_IN_OLD_KEY_COLUMN||')。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——KEY判断——OLE字段存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断NEW字段是否存在
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TAB_COLUMNS WHERE OWNER = '''||P_IN_KEY_SCHEMA||''' AND TABLE_NAME = '''||P_IN_KEY_MAP||''' AND COLUMN_NAME = '''||P_IN_NEW_KEY_COLUMN||'''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——NEW字段不存在');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('输入的KEY表模式('||P_IN_KEY_SCHEMA||')的KEY表('||P_IN_KEY_MAP||')中不存在NEW_KEY字段('||P_IN_NEW_KEY_COLUMN||')。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——NEW字段存在判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断KEY表是否有数据
SET V_SQL = 'SELECT COUNT(1) FROM '||P_IN_KEY_SCHEMA||'. '||P_IN_KEY_MAP;
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS = 0 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——KEY表无数据');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('输入的KEY表模式('||P_IN_KEY_SCHEMA||')的KEY表('||P_IN_KEY_MAP||')中无数据。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——KEY判断——KEY表是否为空判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 判断字段是否一一对应
SET V_SQL = 'SELECT COUNT(1)
FROM (
SELECT COUNT(DISTINCT '||P_IN_OLD_KEY_COLUMN||') AS F_DIS_OLD_CNT,
COUNT(DISTINCT '||P_IN_NEW_KEY_COLUMN||') AS F_DIS_NEW_CNT
FROM '||P_IN_KEY_SCHEMA||'.'||P_IN_KEY_MAP||') T
WHERE T.F_DIS_OLD_CNT = T.F_DIS_NEW_CNT
AND T.F_DIS_NEW_CNT = '||V_IS_EXISTS;
EXECUTE IMMEDIATE V_SQL INTO V_IS_VAILD;
IF V_IS_VAILD < 1 THEN
INSERT INTO LOG_SP_RUN(SP_NAME,STATUS,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',1,V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'错误,判断部分——KEY判断——数据非一一对应');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
PRINT('KEY表模式('||P_IN_KEY_SCHEMA||')的KEY表('||P_IN_KEY_MAP||')中的字段值非一一对应或存在重复值。请检查输入模式名、表名或字段名是否正确。');
RETURN;
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'判断部分——KEY判断——数据一一对应判断完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
/*操作部分*/
-- 操作临时表
-- 创建临时表1
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TABLES WHERE OWNER = '''||P_IN_SCHEMA||''' AND TABLE_NAME = ''TMP_SP_REPLACE_KEY_TB_1''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_1;';
COMMIT;
END IF;
EXECUTE IMMEDIATE 'CREATE TABLE '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_1(F_UNQ_COL VARCHAR(4000),F_TAG_COL VARCHAR(4000))';
EXECUTE IMMEDIATE 'INSERT INTO '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_1(F_UNQ_COL,F_TAG_COL) SELECT TO_CHAR('||P_IN_UNQ_COLUMN||'),'||P_IN_TAG_COLUMN||' FROM '||P_IN_SCHEMA||'.'||P_IN_TABLE||'';
COMMIT;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——临时表1完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 删除临时表2
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TABLES WHERE OWNER = '''||P_IN_SCHEMA||''' AND TABLE_NAME = ''TMP_SP_REPLACE_KEY_TB_2''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_2';
END IF;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——临时表2删除成功');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 创建临时表3
SET V_SQL = 'SELECT COUNT(1) FROM ALL_TABLES WHERE OWNER = '''||P_IN_SCHEMA||''' AND TABLE_NAME = ''TMP_SP_REPLACE_KEY_TB_3''';
EXECUTE IMMEDIATE V_SQL INTO V_IS_EXISTS;
IF V_IS_EXISTS = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_3';
END IF;
EXECUTE IMMEDIATE 'CREATE TABLE '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_3(F_UNQ_COL VARCHAR(4000),F_TAG_COL VARCHAR(4000))';
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——临时表3完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 拼接SQL、循环操作部分
-- 计算需要修改的字段中,最多需要更新的编码数量
SET V_SQL = 'SELECT MAX(F_ZM_CNT) FROM (SELECT REGEXP_COUNT(F_TAG_COL,'','') + 1 AS F_ZM_CNT FROM '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_1) T';
EXECUTE IMMEDIATE V_SQL INTO V_MAX_CNT;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——循环次数为:'||V_MAX_CNT);
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 拼接部分语句,通过循环增加字段数量
SET V_CREATE_TB_SQL = 'CREATE TABLE '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_2(F_UNQ_COL VARCHAR(4000)';
SET V_INSERT_TB_SQL_I = 'INSERT INTO '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_2(F_UNQ_COL';
SET V_INSERT_TB_SQL_V = 'SELECT F_UNQ_COL';
SET V_CONCAT_COL_SQL = 'INSERT INTO '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_3(F_UNQ_COL,F_TAG_COL) SELECT F_UNQ_COL,CONCAT(';
-- 循环拼接语句
FOR I IN 1.. V_MAX_CNT LOOP
SELECT CONCAT(V_CREATE_TB_SQL,',F_COL_',TO_CHAR(I),' VARCHAR(50)') INTO V_CREATE_TB_SQL;
SELECT CONCAT(V_INSERT_TB_SQL_I,',F_COL_',TO_CHAR(I)) INTO V_INSERT_TB_SQL_I;
SELECT CONCAT(V_INSERT_TB_SQL_V,',REGEXP_SUBSTR(F_TAG_COL,''[^,]+'',1,',TO_CHAR(I),')') INTO V_INSERT_TB_SQL_V;
SELECT CONCAT(V_CONCAT_COL_SQL,'(CASE WHEN F_COL_',TO_CHAR(I),' IS NOT NULL THEN CONCAT(F_COL_',TO_CHAR(I),','','') ELSE '''' END),') INTO V_CONCAT_COL_SQL;
END LOOP;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——循环拼接语句完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 创建临时表2
SELECT CONCAT(V_CREATE_TB_SQL,')') INTO V_CREATE_TB_SQL;
EXECUTE IMMEDIATE V_CREATE_TB_SQL;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——临时表2创建完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 执行拼接的插入语句,将字段分成多列插入临时表2中
SELECT CONCAT(V_INSERT_TB_SQL_I,') ',V_INSERT_TB_SQL_V,' FROM ',P_IN_SCHEMA,'.TMP_SP_REPLACE_KEY_TB_1') INTO V_INSERT_TB_SQL_RESULT;
EXECUTE IMMEDIATE V_INSERT_TB_SQL_RESULT;
COMMIT;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——临时表2数据插入完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 循环按列更新临时表2的编码
FOR I IN 1.. V_MAX_CNT LOOP
SET V_SQL = 'UPDATE '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_2 A SET A.F_COL_'||TO_CHAR(I)||' = (SELECT '||P_IN_NEW_KEY_COLUMN||' FROM '||P_IN_KEY_SCHEMA||'.'||P_IN_KEY_MAP||' B WHERE A.F_COL_'||TO_CHAR(I)||' = B.'||P_IN_OLD_KEY_COLUMN||')';
EXECUTE IMMEDIATE V_SQL;
COMMIT;
END LOOP;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——循环更新临时表2完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 拼接语句,将临时表2中分开的编码列重新合为一列,并插入到临时表3之中
SELECT CONCAT(RTRIM(V_CONCAT_COL_SQL,','),') FROM ',P_IN_SCHEMA,'.TMP_SP_REPLACE_KEY_TB_2') INTO V_CONCAT_COL_SQL;
EXECUTE IMMEDIATE V_CONCAT_COL_SQL;
COMMIT;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——临时表2合并插入临时表3完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
-- 使用临时表3更新数据表
EXECUTE IMMEDIATE 'UPDATE '||P_IN_SCHEMA||'.'||P_IN_TABLE||' A SET A.'||P_IN_TAG_COLUMN||' = (SELECT RTRIM(F_TAG_COL,'','') FROM '||P_IN_SCHEMA||'.TMP_SP_REPLACE_KEY_TB_3 B WHERE A.'||P_IN_UNQ_COLUMN||' = B.F_UNQ_COL)';
COMMIT;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'操作部分——临时表3更新目标表完成');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
INSERT INTO LOG_SP_RUN(SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES('SP_REPLACE_KEY',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'运行结束');
COMMIT;
EXCEPTION
WHEN OTHERS THEN
PRINT SQLCODE ||':' ||SQLERRM;
END;
主控程序
CREATE OR REPLACE PROCEDURE SP_BATCH_REPLACE()
AS
V_LOG_NUM INT;
V_START_TIME TIMESTAMP(6);
V_PARA_VALUE VARCHAR(800);
V_IN_SCHEMA VARCHAR(400);
V_IN_TABLE VARCHAR(400);
V_IN_UNQ_COLUMN VARCHAR(400);
V_IN_TAG_COLUMN VARCHAR(400);
V_IN_KEY_SCHEMA VARCHAR(400);
V_IN_KEY_MAP VARCHAR(400);
V_IN_OLD_KEY_COLUMN VARCHAR(400);
V_IN_NEW_KEY_COLUMN VARCHAR(400);
CURSOR CUR1 IS
SELECT F_IN_SCHEMA,F_IN_TABLE,F_IN_UNQ_COLUMN,F_IN_TAG_COLUMN,
F_IN_KEY_SCHEMA,F_IN_KEY_MAP,F_IN_OLD_KEY_COLUMN,F_IN_NEW_KEY_COLUMN
FROM TB_BATCH_REPLACE;
BEGIN
SET V_LOG_NUM = 1;
SET V_START_TIME = NOW;
SET V_PARA_VALUE = 'SP_BATCH_REPLACE()';
INSERT INTO LOG_SP_RUN(IS_BATCH,SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES(1,'SP_BATCH_REPLACE',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'开始运行');
SET V_LOG_NUM = V_LOG_NUM + 1;
COMMIT;
OPEN CUR1;
LOOP
-- 获取游标中的内容
FETCH CUR1 into V_IN_SCHEMA,V_IN_TABLE,V_IN_UNQ_COLUMN,V_IN_TAG_COLUMN,V_IN_KEY_SCHEMA,V_IN_KEY_MAP,V_IN_OLD_KEY_COLUMN,V_IN_NEW_KEY_COLUMN;
EXIT WHEN CUR1%NOTFOUND;
CALL SP_REPLACE_KEY(V_IN_SCHEMA,V_IN_TABLE,V_IN_UNQ_COLUMN,V_IN_TAG_COLUMN,V_IN_KEY_SCHEMA,V_IN_KEY_MAP,V_IN_OLD_KEY_COLUMN,V_IN_NEW_KEY_COLUMN);
END LOOP;
CLOSE CUR1;
COMMIT;
INSERT INTO LOG_SP_RUN(IS_BATCH,SP_NAME,SP_LOG_NUM,START_TIME,CURR_TIME,SP_PARA_VALUE,REMARK) VALUES(1,'SP_BATCH_REPLACE',V_LOG_NUM,V_START_TIME,NOW,V_PARA_VALUE,'运行结束');
COMMIT;
EXCEPTION
WHEN OTHERS THEN
PRINT SQLCODE ||':' ||SQLERRM;
END;
文章
阅读量
获赞