Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQL Abfrage - sehr langer IN-Wert (https://www.delphipraxis.net/106755-sql-abfrage-sehr-langer-wert.html)

vsti 16. Jan 2008 09:57

Datenbank: Firebird • Version: 1.5 • Zugriff über: dbExpress

SQL Abfrage - sehr langer IN-Wert
 
Moin moin,

folgende Ausgangssituation:
Es gibt zwei Datenbanken. In der einen liegen die zentralen Kundendaten und in der anderen werden für jede Filiale lokal die Statisikdaten festgehalten.
Wenn ich nun für die Statistik die Kunden nach Kundennummer eingrenzen möche, muss ich das so oder so ähnlich machen:

Delphi-Quellcode:
QueryZentral.sql.text:='select id from kunden where kundennummer between ''001'' and ''101''';
QueryZentral.open;
ids:='';
while not QueryZentral.eof do begin
  ids:=ids+QueryZentral.fieldbyname('id').asstring+',';
  QueryZentral.next;
end;
delete(ids,length(ids),1);

QueryLokal.sql.text:='select sum(umsatz) from stat where kunden_id in ('+ids+')';
QueryLokal.open;
Ja, stimmt, das System ist nicht grade optimal aufgebaut, aber so ist leider mein Ausgangspunkt :(

Jetzt kann man sich denken wo das Problem liegt... das SQL-Statement kann bei vielen Kunden sehr lang werden.

Heterogene Datenbankverbindungen werden von Firebird/Interbase ja leider nicht unterstützt.

Kann man das Problem anders angehen?

Habs auch mal mit Parametern versucht, à la:

Delphi-Quellcode:
QueryLokal.sql.text:='select sum(umsatz) from stat where kunden_id in (:IDS)';
QueryLokal.parambyname('IDS').asstring:=ids;
QueryLokal.open;
was natürlich nicht geht.

Bin dankbar über Anregungen.

marabu 16. Jan 2008 10:04

Re: SQL Abfrage - sehr langer IN-Wert
 
Hallo,

mir schwebt da eher so etwas vor:

SQL-Code:
SELECT SUM(umsatz)
FROM stat
WHERE kunden_id IN (
  SELECT id
  FROM kunden
  WHERE kundennummer BETWEEN :low AND :high
)
Grüße vom marabu

DeddyH 16. Jan 2008 10:06

Re: SQL Abfrage - sehr langer IN-Wert
 
Die IDs werden ja wahrscheinlich nummerisch sein. Dann würde ich mir mit Format behelfen.
Delphi-Quellcode:
QueryLokal.sql.text := Format('select sum(umsatz) from stat where kunden_id in (%s)',[ids]);
QueryLokal.open;

vsti 16. Jan 2008 10:14

Re: SQL Abfrage - sehr langer IN-Wert
 
@marabu:
Das würde voraussetzen, dass ich die beiden Datenbanken heterogen verbinden kann, was toll wäre, aber Firebird leider nicht unterstützt.

@DeddyH:
Das würde aufs Selbe hinauslaufen wie mein erster Versuch.

Was ich nicht erwähnt habe, bei vielen Kunden wird das Statement abgeschnitten und dann bekomme ich eine "unexpected end of comment" Servermeldung.

marabu 16. Jan 2008 10:37

Re: SQL Abfrage - sehr langer IN-Wert
 
Da stand tatsächlich Datenbanken und nicht Tabellen, sorry.

Durch den (bei allen RDBMs) an mehreren Stellen begrenzten Speicherplatz für ein SQL-Statement kommst du irgendwann nicht um ein Subselect herum. Da Firebird SQL nur mit einer einzigen Datenbank arbeiten kann, musst du zuerst die Tabelle mit den ID-Werten lokal aufbauen oder eine Abstraktionsebene finden, die dir das abnimmt und dich das SQL Statement mit zwei Datenbanken formulieren lässt.

Freundliche Grüße

sirius 16. Jan 2008 10:43

Re: SQL Abfrage - sehr langer IN-Wert
 
Ich hatte ein ähnliches Problem (und habs eigentlich auch noch). Bei mir war es allerdings in einer DB, aber dafür ging kein subselect. Also gleich Ausgangssituation (bis auf DB: Oracle) -> viele IDs
Ich würde mich auch für eine andere Lösung interessieren, aber bisher habe ich die IDs geteilt:
SQL-Code:
where ID in (...)
or   ID in (...)
or   ID in (...)
Ich find es nicht elegant, aber seitdem geht es.

marabu 16. Jan 2008 10:47

Re: SQL Abfrage - sehr langer IN-Wert
 
Dein Ansatz verhindert lange Literale, aber doch nicht das Verstümmeln des Statements beim Überschreiten der Statement-Puffergröße (meistens 32KB oder 64KB). Oder entgeht mir da etwas?

vsti 16. Jan 2008 10:50

Re: SQL Abfrage - sehr langer IN-Wert
 
Nein, genau das war meine Vermutung. Sprich: temporäre Tabelle lokal befüllen und darauf das Subselect.
Was das wieder dauern wird, 5000 Inserts auszuführen ;)

Ich weiß bescheid, vielen Dank

Edit: man kann über Parameter große Blobs übergeben, daher hatte ich darauf gehofft. Ist das evtl. ein anderer Ansatz?

alzaimar 16. Jan 2008 11:17

Re: SQL Abfrage - sehr langer IN-Wert
 
Zitat:

Zitat von vsti
Was das wieder dauern wird, 5000 Inserts auszuführen ;)

Wenn Du jeweils mehrere INSERTS in einer Transaktion ausführst, dann sollte das verdammt schnell gehen.

Erstelle Dir eine Stringlist mit allen INSERT-Befehlen und schicke diesen Batch gesammelt zum Server.

PS: Derjenige, der sich in deinem Fall die getrennten Datenbanken ausgedacht hat, sollte geteert und gefedert werden. :zwinker:

mkinzler 16. Jan 2008 11:20

Re: SQL Abfrage - sehr langer IN-Wert
 
Ab FB2.1 gibt es die List-Funktion:
SQL-Code:
select LIST(id, ',') from kunden where kundennummer between ''001'' and ''101''';
Cross-database Query soll ab FB3 (2,5?) kommen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:08 Uhr.
Seite 1 von 2  1 2      

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 by Thomas Breitkreuz