Zeilenweise Verarbeitung eines TextBlobs

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Antworten
zappa2
Beiträge: 25
Registriert: Fr 5. Okt 2018, 10:59

Ich lese in ein Blob-Feld Typ 1 eine ordinäre CSV-Datei ein.

Diese möchte ich zeilenweise verarbeiten.

Die Zeilen haben keine feste Länge, aber eine feste Feldstruktur. z.B.

id;Entity1;Entity2;IntWert1;IntWert2

Die Feldlängen selbst sind variabel. Das Separieren der einzelnen Feldwerte ist trivial, habe ich ordentlich im Griff.

Habe ich irgendeine Chance (ohne externe Libs), an die einzelnen Zeilen des Blobs zu kommen? Also so eine Art ReadLn...

Ein weiteres Problem ist noch, das ich nicht weiß, wie der Zeilenumbruch aussieht: #10 oder #13#10 oder #13?
Sonst hätte ich es sinngemäß so gemacht:

sub_string(blobfeld from 1 for position(endezeichen));

Klar das ab der nächsten Zeile die letzte Endposition+1 nun die neue Startposition wäre, geschenkt.

Schreibe ich die Zeilen einzeln in die DB, dauert das bei gut 100.000 Sätze über 2Min, als Blob ist die Datei in nicht mal 1 Sekunde in der DB.
Benutzeravatar
martin.koeditz
Beiträge: 313
Registriert: Sa 31. Mär 2018, 14:35

N'Abend,

in Firebird lässt sich der Zeilenumbruch wie folgt darstellen:
ASCII_CHAR(13)||ASCII_CHAR(10)
Hiermit sollte sich das Zeilenende ermitteln lassen.

Gruß
Martin
Martin Köditz
it & synergy GmbH
zappa2
Beiträge: 25
Registriert: Fr 5. Okt 2018, 10:59

Hallo Martin,
vielen Dank für Deine schnelle Antwort.

Das Problem ist aber, dass ich nicht weiß, in welchem Format innerhalb des Blobs die Zeilenumbrüche vorliegen.

Dass es normalerweise ASCII_CHAR(13)||ASCII_CHAR(10) sein sollte, ist mir schon klar. Aber das ist es nicht immer, sondern manchmal nur ASCII_CHAR(13) oder nur ASCII_CHAR(10). Abgesehen davon, wollte ich nicht selbst die Zeilenumbrüche ausrechnen.

Gibt es in der Tat keine Möglichkeit, Text_Blobs sinngemäß wie eine Stringliste, Memo o.ä. auszulesen?
bfuerchau
Beiträge: 289
Registriert: Mo 7. Mai 2018, 18:09

Du kannst den Blob ja auslesen und per Split-Funktion deiner Programmiersprache in Zeilen auflösen.
Beispiel für .Net:

string.split(var, new char[] {'\n', '\r'})

Außerdem:
Per Bulk.Insert (bis 255 Inserts in einem SQL) schafft man 100.000 Zeilen in 5 Sekunden oder sogar kürzer. Auch bereits mit 2.5.
Wichtig ist jedoch die Erkenntnis, dass Parametermarker "?" das Tempo erhöhen.
vr2
Beiträge: 120
Registriert: Fr 13. Apr 2018, 00:13

Hallo zappa2,

Du kannst diese SP dafür einsetzen (die ist auch sonst ganz nützlich):

Code: Alles auswählen

CREATE PROCEDURE SPLIT (
  TEXT BLOB SUB_TYPE 1 SEGMENT SIZE 80,
  TOKEN VARCHAR(100)
)
RETURNS (
  PART VARCHAR(32000),
  POS INTEGER
)
AS
declare newpos int;
declare oldpos int;
declare len int;
begin
  oldpos = 1;
  newpos = 1;
  pos = 0;
  len = char_length(token);
  while (1 = 1) do
  begin
    newpos = position(token, text, oldpos);
    if (newpos > 0) then
    begin
      part = substring(text from oldpos for newpos - oldpos);
      pos = pos + 1;
      suspend;
      oldpos = newpos + len;
    end
    else if (oldpos - len <= char_length(text)) then
    begin
      part = substring(text from oldpos);
      pos = pos + 1;
      suspend;
      break;
    end
    else
      break;
  end
end;
Das Zeilenende kannst Du einmalig aus der ersten Zeile ermitteln und dann als token an split übergeben.

Grüße, vr2
Antworten