Bulk Methoden in PL/SQL sind praktisch und schnell. Auch recht einfach anzuwenden. Allerdings ist mir in Oracle 9.2.0.6 ein sehr komisches Verhalten aufgefallen:
DECLARE TYPE id_table IS TABLE OF NUMBER; objekt_ids id_table; BEGIN SELECT id BULK COLLECT INTO objekt_ids FROM irgendwas WHERE irgendwasanderes = 'wasweißich'; FORALL idx IN objekt_ids.first .. objekt_ids.last DELETE FROM table1 WHERE objekt_id = objekt_ids(idx); FORALL idx IN objekt_ids.first .. objekt_ids.last DELETE FROM table2 WHERE objekt_id = objekt_ids(idx); -- ... END; |
Das Beispiel ist jetzt natürlich erstmal sinnlos, ist aber auch egal. Der Haken an der Sache: Das BULK COLLECT INTO Statement wirft keine NO_DATA_FOUND Exception, wenn die Ergebnismenge leer ist (im Gegensatz zu einem normalen SELECT INTO). Nichts desto trotz ist object_ids danach eine korrekt initialisierte Zusammenstellung.
War die Ergebnismenge leer, gibt es trotzdem eine Exception. Und zwar eine INVALID_NUMBER. Aus irgendeinem Grund laufen die forall Schleifen, auch wenn die virtuelle Tabelle leer ist.
Deshalb gilt für BULK Methoden: Abfragen, ob die Indextabellen leer sind!
DECLARE TYPE id_table IS TABLE OF NUMBER; objekt_ids id_table; BEGIN IF(objekt_ids.COUNT > 0)THEN SELECT id BULK COLLECT INTO objekt_ids FROM irgendwas WHERE irgendwasanderes = 'wasweißich'; FORALL idx IN objekt_ids.first .. objekt_ids.last DELETE FROM table1 WHERE objekt_id = objekt_ids(idx); FORALL idx IN objekt_ids.first .. objekt_ids.last DELETE FROM table2 WHERE objekt_id = objekt_ids(idx); -- ... END IF; END; |
2 Comments
Bin durch zufall auf diese Seite gestoßen!
Vielen Dank für den Hinweis, dass beim Bulk Collect keine NO_DATA_FOUND exception geworfen wird!
Ich habe mich jetzt ca. 1h mit diesem dummen Problem aufgehalten… und habe endlich hier die Lösung gefunden
Schönen Tag noch!
Gerne! Vielen Dank für die nette Rückmeldung!
Post a Comment