注册
拆分分隔符连接的字段串字段并进行更新替换
专栏/培训园地/ 文章详情 /

拆分分隔符连接的字段串字段并进行更新替换

彴约 2024/04/25 1338 1 0
摘要

一、前提

在某个项目之中,由于相关业务调整,客户需要更新数据库中的部分编码。但是编码并不是一个编码存放在一个字段之中,而是在一个字段之中存放多个编码,编码之间使用","分隔,且字段内编码数量不固定,如下所示:

COL 001,002,003 01,001,0011 006 007,008,009,010

这样的编码字段存在于多个表之中,替换存在一定难度。

新旧编码存在对应关系,且为一一对应。但

  1. 旧编码中,部分编码之间存在包含关系,如:01和001;
  2. 新编码中,部分编码之间也存在包含关系;
  3. 且新旧编码存在相同值但对应含义不同。

分析

思路一:

因为新旧编码一一对应,所以考虑使用嵌套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连接,完成更新。
难点在于:

  1. 需要使用合适的方法进行分割
  2. 需要判断拆分次数
  3. 需要对多张表进行操作

首先使用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;
评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服