Oracle
 sql >> Database >  >> RDS >> Oracle

Come eseguire l'operazione batch usando pl/sql

Dirò solo che è disgustoso prima di iniziare. Se stai creando script che automatizzano la creazione del database, abbandonerei la query seguente e andrei semplicemente con copia/incolla perché è così orribile che NON appartiene agli script di distribuzione del tuo database.

La domanda

DECLARE
    CURSOR TABLES IS SELECT * FROM USER_TABLES
                     WHERE 0 = (SELECT COUNT(*)
                                FROM USER_CONSTRAINTS
                                WHERE USER_CONSTRAINTS.TABLE_NAME = USER_TABLES.TABLE_NAME 
                                AND USER_CONSTRAINTS.CONSTRAINT_TYPE = 'P'
                               );
BEGIN
    FOR T IN TABLES LOOP
        EXECUTE IMMEDIATE 'ALTER TABLE '||T.TABLE_NAME||' ADD ID NUMBER(12)';
        EXECUTE IMMEDIATE 'CREATE SEQUENCE '||T.TABLE_NAME||'Seq START WITH 1';
        EXECUTE IMMEDIATE 'UPDATE '||T.TABLE_NAME||' SET ID = '||T.TABLE_NAME||'Seq.NEXTVAL';
        EXECUTE IMMEDIATE 'ALTER TABLE '||T.TABLE_NAME||' ADD PRIMARY KEY (ID)';
        EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER '||T.TABLE_NAME||'PKSet '||CHR(10)
                          ||'BEFORE INSERT ON '||T.TABLE_NAME||' '||CHR(10)
                          ||'FOR EACH ROW '||CHR(10)
                          ||'BEGIN '||CHR(10)
                          ||':NEW.ID := '||T.TABLE_NAME||'Seq.NEXTVAL; '||CHR(10)
                          ||'END; ';
    END LOOP;
END;
/

Che cosa fa?

Fondamentalmente, ottiene un elenco di tabelle e crea dinamicamente l'SQL per eseguire le varie attività coinvolte. EXECUTE IMMEDIATE prende la stringa in cui abbiamo costruito l'SQL e lo esegue. Il CHR(10) la cattiveria è una nuova riga. Volevo lo spazio bianco lì dentro perché non so come lasciarlo fuori avrebbe influito sull'analisi di Oracle. Nota che in diversi punti concateniamo il nome della tabella direttamente a qualche altro testo per generare una sequenza o un nome di vincolo PK.

Questo potrebbe o non potrebbe essere errato se hai citato i nomi delle tabelle durante la creazione e stai utilizzando alcuni caratteri minuscoli. Se si verifica un errore, tieni presente che ogni istruzione implica un commit. Un errore significherà che il processo è a metà. Non riesce anche se lo schema non è l'utente corrente. (Dovrai cambiare USER_TABLES a ALL_TABLES e aggiungi un filtro appropriato nella clausola where e aggiungi lo schema prima del nome della tabella durante la creazione dell'SQL per farlo funzionare su un altro schema.)

Un vero SQLFiddle funzionante:http://sqlfiddle.com/#!4/b67fc/1 (Non posso credere che abbia effettivamente funzionato su SQLFiddle.) In questo caso, la query a cui siamo interessati è finita nella definizione dello schema poiché SQL Fiddle consente solo SELECT nella query.

Buona fortuna. Ne avrai bisogno. Non spararti ai piedi.