Oracleデータ更新の経験を忘れないでください

重要な瞬間に、できるだけ早く配達されます

Oracleデータ更新の経験を忘れないでください

最近、おもしろいトピックを見つけて共有しましたが、私の解決策はかなりばかげているかもしれないので、より良い解決策の提案をしたいと思います。

主題の内容

Oracleデータベースにはテーブルのバッチ(1000を超える)があり、テーブルの一部のフィールドの指定された文字を他の指定された文字に変更する必要があります。TABLE0001、TABLE0002、TABLE0003などのテーブル名は似ていますが、テーブル名は連続していません。TABLE0100、TABLE0200、TABLE0300などのテーブルがない場合があります。フィールド名は類似しており、FIELD001、FIELD002、FIELD003などです。テーブルのフィールド名は固定されていません。フィールドが1つしかないもの、100を超えるフィールドがあるもの、データがないものがあります。ここで、「Zhang San」の文字を含むこれらのテーブルのすべてのフィールドの内容を「LiSi」に変更する必要があり、フィールドの他の文字は変更されません。たとえば、「Zhang San is agoodstudent」のようになります。 「LiSiはいい学生です」へ。

このような問題を見て、最初に頭に浮かぶのは、カーソルを書き込んで繰り返し実行することです。しかし、深く掘り下げていくと、それほど単純ではないことがわかりました。(答えを見たい場合は、記事の最後にあるコード部分にスキップできます)質問は次のように分類されます。


テーブル名の不連続性の問題テーブル名は、データベースにテーブルが存在するかどうかを判断するために連続していません。現時点では、OracleシステムテーブルUSER_TABLES(ユーザーテーブル)からこれらのテーブルを見つけて、一時テーブルに挿入することを考えています。また、テーブル内のレコード数も一緒に挿入されます。これは、0レコードでテーブルをフィルタリングし、後でコンテンツの更新を減らすのに便利です。

クエリステートメントは次のとおりです。

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;

ここでエラーが報告されているのは残念です。エラーの理由は、変数テーブル名CUR.TABLE_NAMEを文字として一時テーブルに挿入し、一時テーブルTEMP_TABLEにクエリを実行して直接知ることができるようにするためです。各テーブルに特定の数のレコードがありますが、動的SQLステートメントは失敗し、別の方法しか見つけることができません。

以下に示すように、トラバースされたテーブルをEXCELに配置して、必要なクエリステートメントを自動的に生成します。

Oracleデータ更新の経験を忘れないでください

Oracleデータ更新の経験を忘れないでください

図EXCELはクエリ文のスプライシングを完了します

次に、これらのスプライスされたクエリステートメントの実行を開始します。次に、各テーブルのデータボリュームをクエリして、一時テーブルTEMP_TABLEに挿入できます。最初のステップは正常に完了しました〜

固定されていないフィールド
の問題は、一貫性のないテーブル名に少し似ていますが、違いもあります。私の最初のアプローチは、すべての列を一覧表示して、その内容を実行することです。

具体的なコードは次のとおりです。


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;

コードはスムーズに実行できますが、問題が見つかります。この列は必ずしも存在しません。実行に列がない場合は、間違いなくエラーが報告されます。データベースエラーは自動的にスキップされません。停止します。これでは効果が得られません!

更なる修正
このコラムは存在しないかもしれませんので、まずは判断させていただきますか?

この考えに従って、コードが変更され、システムテーブルUSER_TAB_COLUMNSは、更新されたテーブルに定義された列名があるかどうかを照会され、存在する場合は更新が実行され、存在しない場合はスキップされます。

具体的なコードは次のとおりです。

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;

結果は成功です。変数v_nameを変更するだけで済みます。1回の実行は非常に高速で、約7秒しかかかりません。

後続の最適化の
最終ステップは完全に自動できます。つまり、最大の列がいくつあるかがわかっている場合は、すべての列をテーブルに配置し、カーソルをループで実行するか、最大値FIELD999を直接取得できます。 、実行中に比較される場合があります。ラウンドごとに列が999回存在するかどうかを判断する必要があるため、時間がかかります。

これまでに、一部のフィールドの内容をバッチで修正および変更する機能は完了しています。

少し考えたこと
が、このトピックからの私の小さな考えのきっかけとなりました。良いことも悪いこともあります。

他の方法で解決できる問題が発生した場合は、木に吊るさないでください。最初のステップが見つかりませんでした。このステップにすべての時間を費やすと、それは間違いなく利益を上回ります。仕事でもっと重要なのは効率です。他の方法で問題を解決できる場合は、できるだけ早く方法を変更できます。さらに、問題を洗練することで、思考をより論理的にすることもできます。

悪い点は、問題が発生したときに、書き込みの結果を考慮せずにコードを書き込むだけであるということです。これは実際には非常に時間がかかります。木を切るのではなく、ナイフを研ぐ方がよいでしょう。問題について明確に考えてから対処する方がよいでしょう。

結論
仕事や生活の中で問題にぶつかることは避けられません。自分の考えで問題や事柄を作ることができれば、達成感は自明です。多分これはプログラマーの幸せです!

おすすめ

転載: blog.51cto.com/15057820/2656423