![]() |
PL/SQL: Kompilierungsfehler bei FORALL mit Insert
Ich bin nach wie vor dabei mich in PL/SQL einzuarbeiten. (Oracle 9i)
Ich habe derzeit ein Package mit folgender Procedure
SQL-Code:
SEQ_Daten ist eine Sequenz. MeasurementPointID ist ein Integer aus dem Package-Body. Und aData ist ein "Table of ValueElement" wobei ValueElement ein Objekt ist mit den beiden Feldern, die in der Procedure zu sehen sind.
procedure setData(aData in ValueList, count_errors out Integer) is
i Number; begin -- count_errors:=0; if MeasurementPointID<>0 then for i in aData.First .. aData.Last loop Insert Into DBT_DATEN(ID, ID_MESSORT, ZEIT, MESSWERT) values (SEQ_DATEN.NEXTVAL, MeasurementPointID, aData(i).ODATETIME , aData(i).OVALUE); end loop; end if; end; Der oben gezeigt Code funktioniert auch. Nun würde ich gerne aus der For-Schleife eine FORALL-Schleife basteln:
SQL-Code:
Das will aber nicht. Egal wo ich Doppelpunkte hinsetze. Ich habe auch schon die Sequenz und die anderen Werte durch Konstanten ersetzt. In SQLPlus bekomme ich nur, dass es nicht kompilierbar ist und im Enterprise Manager sagt er gar nichts und kompiliert halt nicht (wie bei allen Fehlern).
procedure setData(aData in ValueList, count_errors out Integer) is
i Number; begin -- count_errors:=0; if MeasurementPointID<>0 then forall i in aData.First .. aData.Last loop Insert Into DBT_DATEN(ID, ID_MESSORT, ZEIT, MESSWERT) values (SEQ_DATEN.NEXTVAL, MeasurementPointID, aData(i).ODATETIME , aData(i).OVALUE); end if; end; Ich danke jedem für einen Tipp. Edit: Da denkt man den kompletten Nachmittag drüber nach und kurz nachdem man es in die DP eingetragen hat, fällt einem die Lösung auf die Tastatur. Also ich darf (zumindest in Version 9i) nicht Objekte (Bsp.: aData(i).oDateTime) verwenden sondern muss direkt auf Listen verweisen:
SQL-Code:
DateList und ValueList sind jetzt aufgesplittet (Table of Date und Table of Float) und kein "Table of Object" mehr.
procedure setData(aDates in DateList, aValues in ValueList, count_errors out Integer) is
i Number; begin count_errors:=0; if (MeasurementPointID<>0)and(ADates.count=aValues.Count) then FORALL i in aValues.first .. aValues.last SAVE EXCEPTIONS Insert Into DBT_DATEN(ID, ID_MESSORT, ZEIT, MESSWERT) values (SEQ_DATEN.NEXTVAL, MeasurementPointID, aDates(i), aValues(i)); end if; EXCEPTION WHEN OTHERS THEN count_errors := SQL%BULK_EXCEPTIONS.COUNT; end; Falls noch jemand Kommentare hat, dann immer her damit, ansonsten hat sich der Punkt erstmal für mich erledigt :mrgreen: |
Re: PL/SQL: Kompilierungsfehler bei FORALL mit Insert
Warum fängst du die Exception ab?
So weißt du doch gar nicht was schief lief. Außerdem, da du jetzt DOA nutzt, würde ich dir Packages empfehlen. DOA kann die automatisch so verpacken, dass du sie direkt in Delphi nutzen kannst, als wären sie Delphiklassen. Aus Performancegründen, würde ich empfehlen, die Sequencewerte vorher in einem Rutsch zu holen, damit sämtliche Werte statisch sind oder aus gebundenen Bulk-listen kommen.
Delphi-Quellcode:
btw, Enterprise manager stinkt! Schaue dir PL/SQL Developer an, oder die Oracle IDEs von CoreLab.
type TIDList is table of DBT_DATEN.ID%type;
type TDateList is table of DBT_DATEN.Zeit%type; type TMessWertList is table of DBT_DATEN.MessWert%type; procedure SetData(aData in TValueList) is allIDs TIDList := TIDList(); allDates TDateList := TDateList(); allValues TMessWertList := TMessWertList(); begin allIDs.Extend(aData.Count); allDates.Extend(aData.Count); allValues.Extend(aData.Count); for i in aData.First .. aData.Last loop SELECT Seq_Daten.NextVal INTO allIDs(i) FROM dual; allDates(i) := aData(i).ODATETIME; allValues(i) := aData(i).OVALUE; end loop; forall i in allIDs.First .. allIDs.Last INSERT INTO dbt_Daten(ID, ID_MESSORT, ZEIT, MESSWERT) VALUES (allIDS(i), MeasurementPointID, allDates(i) , allValues(i)); end; btw2: Oracle erlaubt es einen Array als Datenquelle zu nutzen. Deine originale SProc könnte also so aussehen:
SQL-Code:
INSERT INTO DBT_DATEN(ID, ID_MESSORT, ZEIT, MESSWERT)
SELECT SEQ_DATEN.NEXTVAL, MeasurementPointID, ODATETIME , OVALUE FROM table(aData); |
Re: PL/SQL: Kompilierungsfehler bei FORALL mit Insert
Danke Robert.
Das mit dem Package und dem Package Wizard in Delphi hatte ich bereits rausgefunden. Ich glaube ich werde die Werte in zwei Listen belassen. Da schadet ja nicht. Es ist von Delphiseite zumindest nicht Bedingung alles in ein Objekt zu schmeißen. Das mit der Sequenz werde ich dankend übernehmen. Das Array als Datenquelle brauch ich vielleicht nochmal. Das mit der Exception finde ich besser so. Das war ja hier nur ein Test und ich sollte schon noch mehr Infos rausholen als nur die Anzahl. Aber wenn ich die Exception nicht abfange, dann schmeißt er mich bei der ersten Wertedopplung (es darf ja nicht zwei Messwerte zum gleichen Zeitpunkt geben) raus. Bisher (Implementation ohne SP) habe ich das auch einfach ignoriert (abgesehen von Meldungen), da es nur passiert wenn jemand zweimal dieselbe Messdatei einliest oder eben einmal unterbrochen wurde und wieder neu anfängt. Das es was besseres gibt als den Enterprise Manager habe ich ich schon gedacht. Das werde ich auch mal angehen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz