Remember an Oracle data update experience

At the critical moment, delivered as soon as possible

Remember an Oracle data update experience

Recently, I saw an interesting topic, and I shared it with you. My solution may be rather stupid, so I would like to offer some suggestions for a better solution.

Subject content

There are a batch of tables in the Oracle database (more than 1000), and the specified characters of some fields in the tables need to be modified to other specified characters. The table names are similar, such as TABLE0001, TABLE0002, TABLE0003, etc., but the table names are not continuous. There may be no tables TABLE0100, TABLE0200, TABLE0300, etc. The field names are similar, such as FIELD001, FIELD002, FIELD003 and so on. The field names of the table are not fixed, some may have only one field, some may have more than 100 fields, and some tables may have no data. Now it is necessary to change the contents of all the fields in these tables that contain the characters "Zhang San" to "Li Si", and the other characters in the fields remain unchanged, for example: "Zhang San is a good student" to "Li Si is a good student".

Seeing such a problem, the first way that comes to mind is to write a cursor to make it execute repeatedly. But as I went deeper, I found that it was not that simple. (If you want to see the answer, you can skip directly to the code part at the end of the article) The question is broken down as follows:

The problem of
table name discontinuity The table name is not continuous to determine whether the table exists in the database. At this time, I think of finding these tables from the Oracle system table USER_TABLES (user table), and then inserting them into a temporary table. And the number of records in the table is also inserted together, it is convenient to filter the table with 0 records, and reduce the content update later.

The query statement is as follows:

DECLARE 
CURSOR CURS ISSELECT TABLE_NAME FROM USER_TABLES 
WHERE TABLE_NAME LIKE 'TABLE%';
v_sql VARCHAR2(4000);
BEGIN
    FOR CUR IN CURS LOOP
    v_sql :=' SELECT  '||''CUR.TABLE_NAME''||',COUNT(1) T_CNT
    INTO TEMP_TABLE FROM '||CUR.TABLE_NAME;
    EXECUTE IMMEDIATE v_sql;
    END LOOP;
END;
END;

It’s a pity that an error has been reported here. The reason for the error is that I want to insert the variable table name CUR.TABLE_NAME as a character into the temporary table, so that I can query the temporary table TEMP_TABLE to directly know the specific number of records in each table, but in the dynamic The SQL statement is unsuccessful and can only find another way.

Put the traversed table in EXCEL to automatically generate the query statement I need, as shown below:

Remember an Oracle data update experience

Remember an Oracle data update experience

Figure EXCEL completes the query sentence splicing

Then start the execution of these spliced ​​query statements to query the data volume of each table and insert it into the temporary table TEMP_TABLE. The first step is successfully completed~


The problem of unfixed fields is a bit similar to the inconsistent table names, but there are also differences. My initial approach is to list all the columns and do what it says.

The specific code is as follows:


DECLARE
CURSOR mycur ISSELECT T_NAME 
FROM TEMP_TABLE WHERE T_CNT<>0 ;
myrecord mycur%ROWTYPE;
v_sql1 VARCHAR2(4000);
v_sql2 VARCHAR2(4000);
v_sql3 VARCHAR2(4000);
v_sql4 VARCHAR2(4000);
v_sql5 VARCHAR2(4000);
BEGINOPEN mycur;
LOOP
FETCH mycur INTO myrecord;
EXIT WHEN mycur%NOTFOUND;
v_sql1 :='UPDATE '||myrecord.T_NAME||' SET
FIELD001=REPLACE(FIELD001,''张三'',''李四'')';
v_sql2 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD002=REPLACE(FIELD002,''张三'',''李四'')';
v_sql3 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD003=REPLACE(FIELD003,''张三'',''李四'')';
v_sql4 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD004=REPLACE(FIELD004,''张三'',''李四'')';
v_sql5 :='UPDATE '||myrecord.T_NAME||' SET 
FIELD005=REPLACE(FIELD005,''张三'',''李四'')';
EXECUTE IMMEDIATE v_sql1;
EXECUTE IMMEDIATE v_sql2;
EXECUTE IMMEDIATE v_sql3;
EXECUTE IMMEDIATE v_sql4;
EXECUTE IMMEDIATE v_sql5;
END LOOP;
CLOSE mycur;
END;

The code can be executed smoothly, but a problem is found in it. This column does not necessarily exist. If there is no column in the execution, an error will definitely be reported. The database error will not be automatically skipped for you, and it will stop. This will not achieve the effect!

Further modification
Since this column may not exist, how about let me judge it first?

Following this idea, the code is modified, the system table USER_TAB_COLUMNS is queried whether there is a defined column name in the updated table, if it exists, the update is performed, and if it does not exist, it is skipped.

The specific code is as follows:

DECLARE
--定义游标
CURSOR mycur IS   
--将临时表TEMP_TABLE中记录数不为0的表查询出来
SELECT T_NAME FROM TEMP_TABLE WHERE T_CNT<>0 ;
myrecord mycur%ROWTYPE;
--定义变量
v_sql1 VARCHAR2(4000);
v_count INTEGER;
--定义列变量,
v_name VARCHAR2(20) := 'TABLE0001';
BEGIN
--打开游标
OPEN mycur;
LOOP
FETCH mycur INTO myrecord;
EXIT WHEN mycur%NOTFOUND;
--从系统表USER_TAB_COLUMNS中查询被更新的表中是否存在定义的列名
SELECT COUNT(*) INTO v_count 
FROM USER_TAB_COLUMNS 
WHERE table_name=myrecord.T_NAME 
and column_name=v_name;
--如果存在执行更新
IF v_count>0 THEN
v_sql1 :='UPDATE '||myrecord.T_NAME||' SET 
'||v_name||'=REPLACE('||v_name||',''张三'',''李四'')';
EXECUTE IMMEDIATE v_sql1;
END IF;
END LOOP;
--结束游标
CLOSE mycur;
END;

The result is successful, you only need to modify the variable v_name. It is very fast to execute once, and only takes about 7 seconds.

The
final step of subsequent optimization can be fully automated, which is to put all the columns in a table and execute the cursor in a loop, provided that you know how many of the largest columns are, or you can directly take the maximum value FIELD999, which may compare during execution. Time-consuming, because every round he has to judge whether the column exists 999 times.

So far, the function of rectifying and modifying the contents of some fields in batches has been completed.

A little thinking
triggered my little thinking from this topic, both good and bad.

The good thing is that if you encounter a problem that can be solved by other means, don't hang it on a tree. The first step has not been found. If you put all your time on this step, it will definitely outweigh the gain. What is more important at work is efficiency. If you can use other methods to solve the problem, you can change the method as soon as possible. In addition, refining the problem can also make thinking more logical.

The bad thing is that when you encounter a problem, you just write the code without thinking about the result of the writing. This is actually very time-consuming. It is better to sharpen the knife and not to chop the wood. It will be better to think about the problem clearly and then deal with it.

Conclusion
It is inevitable that you will encounter some problems in work and life. When you can make a problem or thing through your own thinking, the sense of accomplishment is self-evident. Maybe this is the happiness of programmers!

Guess you like

Origin blog.51cto.com/15057820/2656423