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

テーブルの FK リレーションに基づいて、PL/SQL で DELETE ステートメントを生成する方法は?

    (私の最初の回答は長すぎて編集が難しくなり、コミュニティ ウィキ化されました。これは本当に面倒です。これがスクリプトの最新バージョンです。)

    このスクリプトは、再帰によってカスケード削除を実行しようとします。循環参照がある場合は、無限ループを回避する必要があります。ただし、すべての循環参照制約に ON DELETE SET NULL が必要です または ON DELETE CASCADE .

    CREATE OR REPLACE PROCEDURE delete_cascade(
        table_owner          VARCHAR2,
        parent_table         VARCHAR2,
        where_clause         VARCHAR2
    ) IS
        /*   Example call:  execute delete_cascade('MY_SCHEMA', 'MY_MASTER', 'where ID=1'); */
    
        child_cons     VARCHAR2(30);
        parent_cons    VARCHAR2(30);
        child_table    VARCHAR2(30);
        child_cols     VARCHAR(500);
        parent_cols    VARCHAR(500);
        delete_command VARCHAR(10000);
        new_where_clause VARCHAR2(10000);
    
        /* gets the foreign key constraints on other tables which depend on columns in parent_table */
        CURSOR cons_cursor IS
            SELECT owner, constraint_name, r_constraint_name, table_name, delete_rule
              FROM all_constraints
             WHERE constraint_type = 'R'
               AND delete_rule = 'NO ACTION'
               AND r_constraint_name IN (SELECT constraint_name
                                           FROM all_constraints
                                          WHERE constraint_type IN ('P', 'U')
                                            AND table_name = parent_table
                                            AND owner = table_owner)
               AND NOT table_name = parent_table; -- ignore self-referencing constraints
    
    
        /* for the current constraint, gets the child columns and corresponding parent columns */
        CURSOR columns_cursor IS
            SELECT cc1.column_name AS child_col, cc2.column_name AS parent_col
              FROM all_cons_columns cc1, all_cons_columns cc2
             WHERE cc1.constraint_name = child_cons
               AND cc1.table_name = child_table
               AND cc2.constraint_name = parent_cons
               AND cc1.position = cc2.position
            ORDER BY cc1.position;
    BEGIN
        /* loops through all the constraints which refer back to parent_table */
        FOR cons IN cons_cursor LOOP
            child_cons   := cons.constraint_name;
            parent_cons  := cons.r_constraint_name;
            child_table  := cons.table_name;
            child_cols   := '';
            parent_cols  := '';
    
            /* loops through the child/parent column pairs, building the column lists of the DELETE statement */
            FOR cols IN columns_cursor LOOP
                IF child_cols IS NULL THEN
                    child_cols  := cols.child_col;
                ELSE
                    child_cols  := child_cols || ', ' || cols.child_col;
                END IF;
    
                IF parent_cols IS NULL THEN
                    parent_cols  := cols.parent_col;
                ELSE
                    parent_cols  := parent_cols || ', ' || cols.parent_col;
                END IF;
            END LOOP;
    
            /* construct the WHERE clause of the delete statement, including a subquery to get the related parent rows */
            new_where_clause  :=
                'where (' || child_cols || ') in (select ' || parent_cols || ' from ' || table_owner || '.' || parent_table ||
                ' ' || where_clause || ')';
    
            delete_cascade(cons.owner, child_table, new_where_clause);
        END LOOP;
    
        /* construct the delete statement for the current table */
        delete_command  := 'delete from ' || table_owner || '.' || parent_table || ' ' || where_clause;
    
        -- this just prints the delete command
        DBMS_OUTPUT.put_line(delete_command || ';');
    
        -- uncomment if you want to actually execute it:
        --EXECUTE IMMEDIATE delete_command;
    
        -- remember to issue a COMMIT (not included here, for safety)
    END;
      

    1. PL / SQLにはJavaと同等のStringTokenizerがありますか?

    2. DATEとTIMEからDATETIMEを作成する

    3. mysqlは交差します

    4. 文字列内の各文字を行に変換します