Ich werde nur sagen, dass das ekelhaft ist, bevor ich anfange. Wenn Sie Skripte erstellen, die die Datenbankerstellung automatisieren, würde ich die folgende Abfrage fallen lassen und einfach mit Kopieren/Einfügen fortfahren, da dies so schrecklich ist, dass es NICHT in Ihre Datenbankbereitstellungsskripte gehört.
Die Abfrage
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;
/
Was bewirkt das?
Grundsätzlich erhält es eine Liste von Tabellen und erstellt dynamisch die SQL, um die verschiedenen damit verbundenen Aufgaben zu erledigen. EXECUTE IMMEDIATE
nimmt die Zeichenfolge, in der wir das SQL erstellt haben, und führt es aus. Der CHR(10)
Gemeinheit ist ein Zeilenumbruch. Ich wollte den Leerraum dort haben, weil ich nicht weiß, wie sich das Weglassen auf die Analyse von Oracle auswirken würde. Beachten Sie, dass wir an mehreren Stellen den Tabellennamen direkt mit anderem Text verketten, um einen Sequenz- oder PK-Constraint-Namen zu generieren.
Dies kann zu einem Fehler führen oder auch nicht, wenn Sie Ihre Tabellennamen während der Erstellung in Anführungszeichen gesetzt haben und einige Kleinbuchstaben verwenden. Wenn es einen Fehler gibt, denken Sie daran, dass jede Anweisung einen Commit beinhaltet. Ein Fehler bedeutet, dass der Vorgang zur Hälfte abgeschlossen ist. Es schlägt auch fehl, wenn das Schema nicht der aktuelle Benutzer ist. (Sie müssen USER_TABLES
ändern zu ALL_TABLES
und fügen Sie einen geeigneten Filter in die where-Klausel ein und fügen Sie das Schema vor dem Tabellennamen hinzu, wenn Sie die SQL erstellen, damit sie auf einem anderen Schema funktioniert.)
Ein tatsächlich funktionierendes SQLFiddle:http://sqlfiddle.com/#!4/b67fc/1 (Ich kann nicht glauben, dass dies bei SQLFiddle tatsächlich funktioniert hat.) In diesem Fall ist die Abfrage, an der wir interessiert sind, in der Schemadefinition beendet, da SQL Fiddle nur SELECT
zulässt in der Abfrage.
Viel Glück. Du wirst es brauchen. Schieß dir nicht in den Fuß.