Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Querystring präparieren (https://www.delphipraxis.net/201611-querystring-praeparieren.html)

Codehunter 7. Aug 2019 09:48

Datenbank: Firebird • Version: 2.5 • Zugriff über: FIBplus

Querystring präparieren
 
Hallo!

Ich habe eine Stored Procedure, die ich (abhängig von Importlisten) u.U. viele tausende Male aufrufen muss. Bisher habe ich da immer TpFIBStoredProc verwendet und die Prozedurparameter mit ParamByName zugewiesen. Das wird aber in so großen Schleifen zum Flaschenhals.

Nun habe ich überlegt, den Querystring wie z.B.:
Code:
EXECUTE PROCEDURE MY_PROC(:Param1,:Param2,:Param3)
in einer Stringliste zu sammeln und dann über TpFIBScripter als EXECUTE BLOCK an die DB zu senden. Sowas hab ich an anderer Stelle schon mehrfach gemacht. Allerdings muste ich dort nur Integers als Parameter übergeben, weshalb ich mir das Präparieren gespart habe. Hier sind es jetzt aber Strings. Gibt es denn innerhalb der FIBplus-Lib eine Funktion, die obigen Query-String mit String-Parametern präparieren kann? Also die reine Stringverarbeitung, ohne das ganze Objekt- und Transaktionsgedöns. Also z.B. sowas in der Art (hier mit einem array of String):

Delphi-Quellcode:
LMyQueryStr := PrepString('EXECUTE PROCEDURE MY_PROC(:Param1,:Param2,:Param3)', [LMyParamStr1, LMyParamStr2, LMyParamStr3]);


Grüße
Cody

hoika 7. Aug 2019 10:09

AW: Querystring präparieren
 
Hallo,

Zitat:

nur Integers als Parameter übergeben, weshalb ich mir das Präparieren gespart habe. Hier sind es jetzt aber Strings.
Was ist denn hier der Unterschied?

Ich würde eher also Execute Procedure sammeln und in einem Block übergeben.#

AFIAK: SP's sind übrigens selber schon prepared, der Query-Plan liegt bereits vor.

Codehunter 7. Aug 2019 10:14

AW: Querystring präparieren
 
Zitat:

Zitat von hoika (Beitrag 1439900)
Ich würde eher also Execute Procedure sammeln und in einem Block übergeben.

Genau das ist das Ziel der Aktion. Einen EXECUTE BLOCK muss ich aber mit fertig formatierten Queries füllen, mit Named Params kann der nicht umgehen. Wie geschrieben, solange die Prozedur nur Integer-Parameter hat konnte ich das einfach mit Format() zusammenbasteln. Bei Strings und der ganzen Quotierung (Stichwort SQL Injection) ist mir das zu heikel.

jobo 7. Aug 2019 11:12

AW: Querystring präparieren
 
Ich bin mir nicht sicher, ob ich das richtig verstanden habe, aber ich glaube, mehr als Du "früher" gemacht hast, geht nicht.

willst du?:
block
EXECUTE PROCEDURE MY_PROC(:Param1,:Param2,:Param3);
EXECUTE PROCEDURE MY_PROC(:Param1,:Param2,:Param3);
EXECUTE PROCEDURE MY_PROC(:Param1,:Param2,:Param3);
endblock

und die unterschiedlich befüllen?
Dann musst Du m.E. auf die Parameterobjekte verzichten und Klartext eintragen.

Alternative (Idee)
Wenn es immer diese Prozedur ist(jedenfalls nicht ständig andere, also halbewegs feste Parameterliste), die in Schleife gerufen wird, dann eine FB Proc bauen, die diesen Aufruf in einer Loop macht und die Parameter in einer Extra Tabelle dafür eintragen.

Parameter für diese "Super SP" wäre ggF. ein Range, Flag oder Stichdatum für beschränkung der Parametertabelle.

MyRealName 7. Aug 2019 11:18

AW: Querystring präparieren
 
Warum nicht andersherum.
Kann denn die DB wissen, welche Liste du sendest ? Zum Bsp. Selbst durch ein query herausfinden und du machst in der stored proc eine FOR SELECT Schleife ?
Oder Du nimmst eine Global Temporary Table und füllst die mit Deiner Liste und dann machst Du das oben mit der FOR SELECT auf die GTT.

(GTT damit mehrere Benutzer das zur Not gleichzeitig könnten).

Codehunter 7. Aug 2019 11:19

AW: Querystring präparieren
 
Wenn ich es recht überlege, habe ich wohl schlicht einen Schritt zu weit gedacht. Eigentlich brauche ich ja nichts weiter als das Delphi-Firebird-Äquivalent zu mysqli_real_escape_string() bei PHP und Mysqli. Den Rest kann ich wie gehabt mit Format() erledigen.

Schokohase 7. Aug 2019 11:36

AW: Querystring präparieren
 
Warum keine Parameter?

AFAIK ist die Anzahl der Parameter nicht beschränkt.
Delphi-Quellcode:
queryStr := '';

for i := 0 to 1000 do
begin
  queryStr := queryStr + Format( 'EXECUTE PROCEDURE MY_PROC(:Param1_%0d,:Param2_%0d,:Param3_%0d);',[i] ) + sLineBreak;
 
  query.ParamByName( Format('Param1_%0d',[i])).Value := 'wert1';
  query.ParamByName( Format('Param2_%0d',[i])).Value := 'wert2';
  query.ParamByName( Format('Param3_%0d',[i])).Value := 'wert3';
end;

query.SQL.Text := queryStr;
query.Execute();
Kein SQL-Injection Problem

Codehunter 7. Aug 2019 12:07

AW: Querystring präparieren
 
Zitat:

Zitat von Schokohase (Beitrag 1439922)
Kein SQL-Injection Problem

Aber das Flaschenhalsproblem aus #1.

Schokohase 7. Aug 2019 12:29

AW: Querystring präparieren
 
Zitat:

Zitat von Codehunter (Beitrag 1439927)
Zitat:

Zitat von Schokohase (Beitrag 1439922)
Kein SQL-Injection Problem

Aber das Flaschenhalsproblem aus #1.

Aber das
SQL-Code:
EXECUTE PROCEDURE MY_PROC('wert1...ganz lang','wert2...ganz lang','wert3...ganz lang');
EXECUTE PROCEDURE MY_PROC('wert1...ganz lang','wert2...ganz lang','wert3...ganz lang');
EXECUTE PROCEDURE MY_PROC('wert1...ganz lang','wert2...ganz lang','wert3...ganz lang');
EXECUTE PROCEDURE MY_PROC('wert1...ganz lang','wert2...ganz lang','wert3...ganz lang');
EXECUTE PROCEDURE MY_PROC('wert1...ganz lang','wert2...ganz lang','wert3...ganz lang');
ist dann schneller als das
SQL-Code:
EXECUTE PROCEDURE MY_PROC(:p1_0,:p2_0,:p3_0);
EXECUTE PROCEDURE MY_PROC(:p1_1,:p2_1,:p3_1);
EXECUTE PROCEDURE MY_PROC(:p1_2,:p2_2,:p3_2);
EXECUTE PROCEDURE MY_PROC(:p1_3,:p2_3,:p3_3);
EXECUTE PROCEDURE MY_PROC(:p1_4,:p2_4,:p3_4);
mit Parametern?

Da sag ich mal nix mehr zu ...aber als kleiner Wink: Probiere es mal aus

jobo 7. Aug 2019 12:40

AW: Querystring präparieren
 
Ja, ausprobieren ist gut!

Ich denke, je größer der Loopcount, desto eher macht sich das bemerkbar.
Hunderte oder tausende von Aufrufen dauern dann halt mit Parameterbestückung etwas länger.

Mglw. ist das aber nur in der Theorie bemerkbar, weil idR die Größe eines Blocks auch beschränkt ist. Weiß nicht, wie das firebird handhabt.

Am Ende macht es wahrscheinlich keinen großen Unterschied. Dann kommt man an den Punkt, die SP selbst zu optimieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:14 Uhr.
Seite 1 von 3  1 23      

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