![]() |
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:
Ja, stimmt, das System ist nicht grade optimal aufgebaut, aber so ist leider mein Ausgangspunkt :(
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; 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:
was natürlich nicht geht.
QueryLokal.sql.text:='select sum(umsatz) from stat where kunden_id in (:IDS)';
QueryLokal.parambyname('IDS').asstring:=ids; QueryLokal.open; Bin dankbar über Anregungen. |
Re: SQL Abfrage - sehr langer IN-Wert
Hallo,
mir schwebt da eher so etwas vor:
SQL-Code:
Grüße vom marabu
SELECT SUM(umsatz)
FROM stat WHERE kunden_id IN ( SELECT id FROM kunden WHERE kundennummer BETWEEN :low AND :high ) |
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; |
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. |
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 |
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:
Ich find es nicht elegant, aber seitdem geht es.
where ID in (...)
or ID in (...) or ID in (...) |
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?
|
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? |
Re: SQL Abfrage - sehr langer IN-Wert
Zitat:
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: |
Re: SQL Abfrage - sehr langer IN-Wert
Ab FB2.1 gibt es die List-Funktion:
SQL-Code:
Cross-database Query soll ab FB3 (2,5?) kommen.
select LIST(id, ',') from kunden where kundennummer between ''001'' and ''101''';
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:08 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 by Thomas Breitkreuz