sql >> データベース >  >> RDS >> Oracle

依存行を含むDBからの行の抽出

    すでにそれを行うツールがあるかもしれませんが、開始テーブルからすべての行テーブルを任意に抽出することは、それ自体が小さな開発タスクです。すべてを書くことはできませんが、始めることはできます。書き始めましたが、約20分後、無給の回答を約束したいのはもう少し作業であることに気付きました。

    dbms_ouputおよびuser_cons_columns&user_constraintsを使用してソース表の挿入文を作成する再帰的なPL/SQLプロシージャによって最もよく実行されていることがわかります。 NLSパラメータがソースシステムとターゲットシステムで同一であると仮定すると、Oracleはすべてのchar値を暗黙的に正しいデータ型に変換するため、列がchar値であるかのようにすべての挿入を書き込むことで少しごまかすことができます。

    以下のパッケージでは、テーブルに循環関係がある場合に問題が発生することに注意してください。また、以前のバージョンのOracleでは、dbms_outputを使用してバッファスペースが不足する可能性があります。両方の問題は、生成されたSQLをSQLに一意のインデックスを持つステージングテーブルに挿入し、一意のキーの衝突が発生した場合に再帰を中止することで解決できます。以下の大幅な時間の節約は、MakeParamList関数です。この関数は、列のリストを返すカーソルを、コンマ区切りのリスト、またはこれらの列の値を引用符で囲まれたコンマ区切りの形式で表示する単一の式に変換します。テーブルに対するクエリのselect句。

    次のパッケージは、さらに変更するまで実際には機能しないことにも注意してください(私がそれを書くのをやめた理由の1つ):生成された最初の挿入ステートメントは、渡されたconstraint_vals引数が単一の行になるという仮定に基づいています生成されます-もちろん、繰り返しを開始すると、これはほぼ確実に当てはまりません(親の子行が多数あるため)。最初のEXECUTEIMMEDIATE呼び出しの呼び出しで単一の行ではなく複数の行が生成される場合を処理するには、最初のステートメント(および後続の再帰呼び出し)の生成をループ内に変更する必要があります。それを機能させるための基本はここにあります、あなたはただ詳細を挽いて外側のカーソルを機能させる必要があります。

    最後の注意点:このプロシージャを実行して一連の行を生成し、ターゲットシステムに挿入すると、すべての依存データを取得するため、「クリーンな」データセットが生成される可能性はほとんどありません。データは、インポートしなかった他のテーブルに依存する場合があります(たとえば、最初に遭遇する子テーブルには、最初のテーブルとは関係のないテーブルを指す他の外部キーがある場合があります)。その場合は、詳細テーブルから始めて、下ではなく上に向かって作業することをお勧めします。その場合は、スクリプトユーティリティを使用するか、前述のようにSQLをステージングテーブルにシーケンスを使用して挿入し、降順で選択して、生成したステートメントの順序を逆にすることもできます。 。

    呼び出す場合は、コンマで区切った列のリストをconstraint_colsとして渡し、対応するコンマで区切った値のリストをconstraint_valsとして渡します(例:

    )。
    exec Data_extractor.MakeInserts ('MYTABLE', 'COL1, COL2', '99, 105')
    

    CREATE OR REPLACE PACKAGE data_extractor
    IS
       TYPE column_info IS RECORD(
          column_name   user_tab_columns.column_name%TYPE
       );
    
       TYPE column_info_cursor IS REF CURSOR
          RETURN column_info;
    
       FUNCTION makeparamlist(
          column_info   column_info_cursor
        , get_values    NUMBER
       )
          RETURN VARCHAR2;
    
       PROCEDURE makeinserts(
          source_table      VARCHAR2
        , constraint_cols   VARCHAR2
        , constraint_vals   VARCHAR2
       );
    END data_extractor;
    
    
    CREATE OR REPLACE PACKAGE BODY data_extractor
    AS
       FUNCTION makeparamlist(
          column_info   column_info_cursor
        , get_values    NUMBER
       )
          RETURN VARCHAR2
       AS
       BEGIN
          DECLARE
             column_name   user_tab_columns.column_name%TYPE;
             tempsql       VARCHAR2(4000);
             separator     VARCHAR2(20);
          BEGIN
             IF get_values = 1
             THEN
                separator := ''''''''' || ';
             ELSE
                separator := '';
             END IF;
    
             LOOP
                FETCH column_info
                 INTO column_name;
    
                EXIT WHEN column_info%NOTFOUND;
                tempsql := tempsql || separator || column_name;
    
                IF get_values = 1
                THEN
                   separator := ' || '''''', '''''' || ';
                ELSE
                   separator := ', ';
                END IF;
             END LOOP;
    
             IF get_values = 1
             THEN
                tempsql := tempsql || ' || ''''''''';
             END IF;
    
             RETURN tempsql;
          END;
       END;
    
       PROCEDURE makeinserts(
          source_table      VARCHAR2
        , constraint_cols   VARCHAR2
        , constraint_vals   VARCHAR2
       )
       AS
       BEGIN
          DECLARE
             basesql               VARCHAR2(4000);
             extractsql            VARCHAR2(4000);
             tempsql               VARCHAR2(4000);
             valuelist             VARCHAR2(4000);
             childconstraint_vals  VARCHAR2(4000);
          BEGIN
             SELECT makeparamlist(CURSOR(SELECT column_name
                                           FROM user_tab_columns
                                          WHERE table_name = source_table), 0)
               INTO tempsql
               FROM DUAL;
    
             basesql := 'INSERT INTO ' || source_table || '(' || tempsql || ') VALUES (';
    
             SELECT makeparamlist(CURSOR(SELECT column_name
                                           FROM user_tab_columns
                                          WHERE table_name = source_table), 1)
               INTO tempsql
               FROM DUAL;
    
             extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table 
                           || ' WHERE (' || constraint_cols || ') = (SELECT ' 
                           || constraint_vals || ' FROM DUAL)';
    
             EXECUTE IMMEDIATE extractsql
                          INTO valuelist;
    
             -- This prints out the insert statement for the root row
             DBMS_OUTPUT.put_line(basesql || valuelist || ');');
    
             -- Now we construct the constraint_vals parameter for subsequent calls:
             SELECT makeparamlist(CURSOR(  SELECT column_name
                                             FROM user_cons_columns ucc
                                                , user_constraints uc
                                            WHERE uc.table_name = source_table
                                              AND ucc.constraint_name = uc.constraint_name
                                         ORDER BY position)
                                 , 1)
               INTO tempsql
               FROM DUAL;
    
             extractsql := 'SELECT ' || tempsql || ' FROM ' || source_table 
                           || ' WHERE ' || constraint_cols || ' = ' || constraint_vals;
    
             EXECUTE IMMEDIATE extractsql
                          INTO childconstraint_vals;
    
             childconstraint_vals := childconstraint_vals;
    
    -- Now iterate over the dependent tables for this table
    -- Cursor on this statement:
    --    SELECT uc.table_name child_table, uc.constraint_name fk_name
    --      FROM user_constraints uc
    --         , user_constraints ucp
    --     WHERE ucp.table_name = source_table
    --      AND uc.r_constraint_name = ucp.constraint_name;
    
             --   For each table in that statement, find the foreign key 
             --   columns that correspond to the rows
             --   in the parent table
             --  SELECT column_name
             --    FROM user_cons_columns
             --   WHERE constraint_name = fk_name
             --ORDER BY POSITION;
    
             -- Pass that columns into makeparamlist above to create 
             -- the constraint_cols argument of the call below:
    
             -- makeinserts(child_table, ChildConstraint_cols, childconstrain_vals);
          END;
       END;
    END data_extractor;
    


    1. パッケージオラクル内のすべての手順のリストを取得する方法

    2. CakePHP2.0でのOracleデータベースの使用

    3. Oracle GROUP_CONCAT()と同等

    4. 複数のforeachループを使用する場合は、PDOステートメントを複数回使用してください