Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   PL/SQL: Kompilierungsfehler bei FORALL mit Insert (https://www.delphipraxis.net/112928-pl-sql-kompilierungsfehler-bei-forall-mit-insert.html)

sirius 29. Apr 2008 19:06


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:
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;
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.
Der oben gezeigt Code funktioniert auch.

Nun würde ich gerne aus der For-Schleife eine FORALL-Schleife basteln:
SQL-Code:
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;
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).

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:
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;
DateList und ValueList sind jetzt aufgesplittet (Table of Date und Table of Float) und kein "Table of Object" mehr.
Falls noch jemand Kommentare hat, dann immer her damit, ansonsten hat sich der Punkt erstmal für mich erledigt :mrgreen:

Elvis 29. Apr 2008 20:27

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:
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;
btw, Enterprise manager stinkt! Schaue dir PL/SQL Developer an, oder die Oracle IDEs von CoreLab.

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);

sirius 29. Apr 2008 20:57

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 01:10 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz