Zitat von
marabu:
Dazu gibt es in Interbase
SQL den Befehl SUSPEND. Durchforste mal dein Handbuch zum Thema Stored Procedure - vielleicht kann Oracle das ja auch?
Es gibt keine Selectable Procedure in Oracle. (Und wird sie in den nächsten 20 Jahren wohl auch nicht geben
)
@Andreas
Dumme Frage, aber hast du wirklich Indizes auf den Feldern?
Bei migrierten DBs von Ora<9 hat man das "Problem" dass Ora9 nicht mehr automatische Indizes auf Foreign Keys vergibt.
Außerdem kommt es nur noch bescheiden mit nicht/schlecht normalisierten Daten klar.
Die JOIN Syntax ist bei Ora übrigens nicht nötig, da der Optimizer genau erkennt wie du wo welche Tabellen verknüpft.
Bei 30 Tabellen in der From clause wird zwar der erste Lauf durch die Optimierung langsamer, aber effektiv macht es sich nicht wirklich bemerkbar.
Was du machen könntest, wäre diese Liste mit Werten als Array an ein
Package zu übergeben. (wenn es immer eine Liste von x =1 or X = 2 or X = 3,... ist)
Dann nimmst du als rückgabewert wieder eine Liste von Werten. Auf die Art ersparst du dir sämtliche round trips da nur einmal Eine Liste hingeschickt und eine zurückgeschickt werden muss.
Wenn du DOA benutzt, kann du diese Oracle Objekte an deine Delphi Applikation binden. (siehe: TOracleObject, TOracleQuery.SetComplexVariable, TOracleQuery.GetComplexVariable)
ich habe mir eben zum Testen diese Beispieltabelle angelegt:
SQL-Code:
create table JbgTable
(
ID INTEGER not null,
NAME VARCHAR2(255),
FIRSTNAME VARCHAR2(255)
);
alter table JBGTABLE
add constraint JBGTABLE_PK primary key (ID)
using index;
Jetzt braucht man einen Objekttypen, der einem Datensatz entspricht:
SQL-Code:
create or replace type TJbgItem as object
(
Id Integer,
Name VarChar(255),
FirstName VarChar(255)
)
Die Liste, die man zurückbekommen will:
create or replace type TJbgItemList as table of TJbgItem;
Die Liste, die man der Funktion übergibt:
create or replace type TIntegerList as table of Integer;
Das
Package[1]:
SQL-Code:
create or replace
package JbgTest
is
function FetchValues(aIds
in TIntegerList)
return TJbgItemList;
end JbgTest;
SQL-Code:
create or replace
package body JbgTest
is
cursor getRecords(iId
in Integer)
is
SELECT TJbgItem(iId, Name, FirstName)
FROM JbgTable t
WHERE t.Id = iId;
function FetchValues(aIds
in TIntegerList)
return TJbgItemList
is
result TJbgItemList := TJbgItemList();
begin
result.Extend(aIds.
Count);
for i
in aIds.First .. aIds.Last loop
open getRecords(aIds(i));
FETCH getRecords
INTO result(i);
close getRecords;
end loop;
return result;
end;
end JbgTest;
[1] eine einfache Funktion würde auch reichen, bei Packages wird aber wiederholter Zugriff auf einen darin liegenden Cursor etwas schneller.
Aus Mangel an DOA hier zu Hause habe ich es mit einem simplen PL/
SQL Script getestet:
SQL-Code:
declare
Ids TIntegerList := TIntegerList();
result TJbgItemList;
begin
Ids.Extend(:Records);
for i in Ids.First .. Ids.Last loop
Ids(i) := dbms_Random.Value(:MinValue, :MaxValue);
end loop;
result := JbgTest.FetchValues(Ids);
:Returned := result.Count;
end;
Die Tabelle habe ich mit 2*10^6 zufälligen VorName/NachName Kombis füllen lassen.
Wenn ich :Records 1000 übergebe (Wodurch 1000 zufallige IDs gesucht werden) braucht er keine 150 Millisekunden.
Und das obwohl mein kleiner "Server" nur ein Virtual Server auf einer kleineren Maschine ist!
Hihi, endlich mal wieder etwas mit Ora gespielt.