JSON Array in Datenbanktabelle

Rund um die LCL und andere Komponenten
JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Hallo,

ich schreibe von einem JSON Array (Inhalt sind die Daten einer Internet Datenbank Tabelle) die Daten in eine Datenbanktabelle (SQLite3 DB).

Bei 974 Datensätzen und 40 Tabellenfeldern dauert die ganze Operation 3 Minuten und 30 Sekunden.

Weiß jemand einen schnelleren Weg?

Hier meine Prozedur:

Code: Alles auswählen

 
procedure Tfaufueber.Button1Click(Sender: TObject);
var
  inputstring, resultstring: string;
  response: TStringStream;
  so: TJSONParser;
  o, oclone, oclone1: TJSONData;
  strname, strinsert: string;
  i, j, k, l: integer;
  test: string;
begin
  Label1.Caption := datetimetostr(Now, FormatSettings);
  Application.ProcessMessages;
  Screen.Cursor := crHourGlass;
  ZConnection1.Connected := True;
  ZQOrders.Active := True;
  inputstring := 'first=' + 'ALL'; //Gesamtabfrage
 
  response := TStringStream.Create(resultstring);
  with THTTPSend.Create do
    HttpPostURL('http://www.test.de' + '/orderall.php', inputstring,
      response);
  try
    response.Position := 0;
    o := nil;
    oclone := nil;
    so := TJSONParser.Create(response);
    so.UseUTF8;
    o := so.Parse;
    oclone := o.Items[0].Clone;
 
    for i := 0 to TJSONObject(oclone).Count - 1 do
    begin
      oclone1 := nil;
      oclone1 := TJSONObject(oclone.Items[i].Clone);
      ZQOrders.Append;
 
      k := 0;
      for j := 0 to TJSONObject(oclone1).Count - 1 do
      begin
        strname := (TJSONObject(oclone1).Names[j]);
        if k > TJSONObject(oclone1).Count - 1 then
          Break
        else
        begin
          if oclone1.Items[k].AsJSON = UpperCase('NULL') then
            strinsert := ''
          else
          if oclone1.Items[k].AsJSON = 'null' then
            strinsert := ''
          else
          if length(oclone1.Items[k].AsJSON) = 0 then
            strinsert := ''
          else
            strinsert := oclone1.Items[k].AsJSON;
 
          strinsert := StringReplace(strinsert, '"', '', [rfReplaceAll]);
 
          for l := 0 to ZQOrders.FieldCount - 1 do
          begin
            test := ZQOrders.Fields[l].Name;
            if ZQOrders.Fields[l].Name = 'ZQOrders' + strname then
            begin
              if zqorders.FieldDefs.Items[l].DataType = ftFloat then
                strinsert := '0' + strinsert;
 
              if ZQOrders.Fields[l].Name = 'ZQOrdersord_datum' then
                ZQOrders.Fields[l].AsString := ConvertDateFormat(strinsert)
              else
                ZQOrders.Fields[l].AsString := strinsert;
            end;
          end;
 
        end;
        k := k + 1;
      end;
    end;
  finally
    so.Free;
    Screen.Cursor := crDefault;
    Label2.Caption := datetimetostr(now, formatsettings);
  end;
 
Der HTTPPostURL geht ruckzuck.

Die For-Schleifen zum Durchlaufen des JSON Arrays und das Schreiben in die Tabelle dauert.

Danke.

Josef


Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6765
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: JSON Array in Datenbanktabelle

Beitrag von af0815 »

theo hat geschrieben:http://stackoverflow.com/questions/1711631/improve-insert-per-second-performance-of-sqlite
Der Link zeigt genau, wie man gerade im SQL-Serverbereich optimieren muss bzw. kann. Leider werden meist nur wenige Daten bei der Entwicklung genommen und dann ist die Überraschung im 'Real Life' groß.

Bei der obigen App würde ich einmal weggehen von Query.Append und die Insert-Statements in der Query selbst schreiben. Dann bei Zeos die Autocommits deaktiveren, zumindest für den 'Bulk insert'. Dann das Insert-Statement mit Parametern versehen, aber nicht mit ParamsByName füllen sondern direkt über Indexzugriffe auf die Parameter und das Statement nicht in einer Schleife neu erstellen, sondern nur am Anfang der Routine. Der Hintergrund, der Server muss jedesmal das Statement neu übersetzen, optimieren, preparen (ZQuery.Prepare in 7.x meiner Info sogar mit sqlite_prepare_v2 bei SQLite) muss und das kostet viel Zeit.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Hallo,

Danke für die Hinweise.

Ich hab das jetzt so gelöst, daß ich die Values über ein Insert into... absetze. Dauert nur 2 sek.

So:

inster1 into orders values(a,b,c,......), (a1, b1, c1,....), usw.

Das funktioniert prima. Nur nach 500 dieser Values macht er schlapp.

"SQL Error: SQL logic errror or missing database."

Erst dachte ich, es wär was mit den Werten nicht in Ordnung. Da war aber alles richtig.

Ich hab dann mit der Forschleife rumgespielt.

Also erst:

Code: Alles auswählen

for i := 0 to TJSONObject(oclone).Count - 1 do  // TJSONObject(oclone).Count = 974
begin 
... 
erzeugt besagten Fehler
 
Dann:
for i := 0 to 500 do
begin
...
erzeugt ebenfalls besagten Fehler.
 
Dann:
for i := 0 to 499 do
begin
....
kein Fehler. Dauerte nicht ganz 2 sek.
 
Dann:
for i := 495 to TJSONObject(oclone).Count - 1 do
begin
....
 
auch kein Fehler. Da die Schleife unter 500 liegt.

Also, der Abbruch tritt nur auf, wenn mehr als 500 Values nach obigem Beispiel gebildet werden.

Wißt ihr, was das sein könnte?

Danke.

Josef
Zuletzt geändert von Lori am Sa 31. Okt 2015, 13:48, insgesamt 1-mal geändert.
Grund: Highlighter

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Ach ja noch was:

ich hab den SQL Expert Personal als Editor.

Wenn ich in diesen Editor den gesamten String, als alle 974 Value's, in das SQL Statement reinkopiere,funktioniert es einwandfrei.

Wie gesagt, nur in meinem Programm mit Zeos geht es nicht über 500.

Danke.

Josef

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6765
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: JSON Array in Datenbanktabelle

Beitrag von af0815 »

Machst du mehr als 500 Insertstatements hintereinander oder schreibst du allesin ein Statement ? Wenn alles zusammen ist, so kann es sein,das dem Zeos der Buffer für das sqlstatement zu klein wird.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Hallo,

ja, ich schreib Alles in ein Statement

INSERT INTO orders VALUES (),(),(),() usw. In meinem Fall wären das 974 Valuesklammern.

Kann man den Buffer erhöhen?

Wenn ich einzeln abschicke, dauert es fast 3 Min., bis alle 974 Values durch sind. Das ist einfach zu lange.

Danke.

Josef

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6765
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: JSON Array in Datenbanktabelle

Beitrag von af0815 »

Wenn du entsprechende Demodaten und den benõtigten Code zur Verfügung stellst, kann man das sicher optimieren und nicht mit solchen Monstern leben.

Ich habe schon einiges optimiert, das erzeugt Statement von dir ist ja Genial, aber für einen DB Programmierer nicht optimal. :D

Hast du eine Ahnung welchen Unfang (Zeichen) dein Statement hat?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Hallo,

so, jetzt funktioniert es. Ich hab einfach die Zahl der Values im SQL-Statement auf 500 begrenzt.
Ich habe 975 Test-DS mit 50 Feldern.

Das sql-insert läuft in meinem Fall also 2 Mal.

Das Weitere ist aus dem Code ersichtlich. Die Gesamtlaufzeit beträgt 10 sek. (Inclusive Tabelle leeren und wieder befüllen).

Code: Alles auswählen

 
procedure Tfaufueber.Button1Click(Sender: TObject);
var
  inputstring, resultstring: string;
  response: TStringStream;
  so: TJSONParser;
  o, oclone, oclone1: TJSONData;
  strinsert, sumstrinsert, sqlall: string;
  ioclonesplit, iSGCount, i, j, splitcount, splitrest, internK1, internK2: integer;
begin
  StatusBar1.Panels.Items[0].Text := 'Daten laden ...';
  ProgressBar1.Visible := True;
  Label1.Caption := datetimetostr(Now, FormatSettings);
  ZQOrdersDeleteAll.ExecSQL;
  ZConnection1.AutoCommit := False;
  Application.ProcessMessages;
  Screen.Cursor := crHourGlass;
  ZConnection1.Connected := True;
  ZQOrders.Active := True;
  ZQOrders.DisableControls;
 
  // Abfrage der Datensätze mit HttpPostURL (aus Synapse)
  // in orderall.php wird serverseitig der gesamte Tabellenbestand 'orders'
  // mittels SQL abgefragt
  inputstring := 'first=' + 'ALL'; //Gesamtabfrage
  response := TStringStream.Create(resultstring);
  with THTTPSend.Create do
    HttpPostURL('http://www.josefkoller.de' + '/orderall.php', inputstring,
      response);
  ProgressBar1.Position := ProgressBar1.Position + 5;
  Application.ProcessMessages;
  try
    response.Position := 0;
    o := nil;
    oclone := nil;
    so := TJSONParser.Create(response);
    so.UseUTF8;
    o := so.Parse;
 
    // es werden die jeweiligen Ebenen des JSON Arrays in eigene TJSONData's geladen
    // erleichtert das "Durchlaufen" mit Schleifen
    // oclone wäre die Ebene mit den Feldnamen
    oclone := o.Items[0].Clone;
 
    // Aufteilen des SQL Strings auf max. 500 DS
    // und Schreiben der DS Bereiche in ein Stringgrid
    //Beispiel: Zeile 1, Spalte 1 = 0, Zeile 1, Spalte 2 = 499
    splitcount := TJSONObject(oclone).Count div 499;
    for ioclonesplit := 0 to splitcount - 1 do
    begin
 
      StringGrid1.RowCount := ioclonesplit + 1;
      StringGrid1.Cells[0, ioclonesplit] := '0';
      StringGrid1.Cells[1, ioclonesplit] := '499';
    end;
    splitrest := TJSONObject(oclone).Count mod 499;
    if splitrest > 0 then
    begin
      StringGrid1.RowCount := StringGrid1.RowCount + 1;
      StringGrid1.Cells[0, StringGrid1.RowCount - 1] :=
        IntToStr(StrToInt(StringGrid1.Cells[1, StringGrid1.RowCount - 2]) + 1);
      StringGrid1.Cells[1, StringGrid1.RowCount - 1] :=
        IntToStr(TJSONObject(oclone).Count - 1);
    end;
 
    for  iSGCount := 0 to StringGrid1.RowCount - 1 do
    begin
      internK1 := StrToInt(StringGrid1.Cells[0, iSGCount]);
      internK2 := StrToInt(StringGrid1.Cells[1, iSGCount]);
      sqlall := '';
 
      // Version mit Split (auf max. 500 DS)
      for i := (internK1) to (internK2) do
 
      // Version ohne Split (975 DS)
      //for i := 0 to TJSONObject(oclone).Count - 1 do
      begin
 
        // Anzeige Progressbar und Statusbartext
        Application.ProcessMessages;
        ProgressBar1.Position := ProgressBar1.Position + 1;
        StatusBar1.Panels.Items[2].Text :=
          'Datensatz ' + IntToStr(i) + ' von ' + IntToStr(TJSONObject(oclone).Count - 1) +
          ' geladen.';
        if ProgressBar1.Position = 100 then
        begin
          ProgressBar1.Position := 1;
          ProgressBar1.Position := ProgressBar1.Position + 1;
        end;
        Application.ProcessMessages;
 
        // es werden die jeweiligen Ebenen des JSON Arrays in eigene TJSONData's geladen
        // erleichtert das "Durchlaufen" mit Schleifen
        // oclone1 wäre die Ebene mit den Values
        oclone1 := nil;
        oclone1 := TJSONObject(oclone.Items[i].Clone);
        strinsert := '';
        for j := 0 to TJSONObject(oclone1).Count - 1 do
        begin
 
          // im json array sind die DS doppelt. einmal mit Feldnamen 0, 1, 2, usw.
          // einmal mit ord_id, ord_forid, usw.
          //mit odd wird die jeweils doppelte Zeile übersprungen
          if Odd(j) then
          else
          begin
            if oclone1.Items[j].AsJSON = 'null' then
              strinsert := '""'
            else
            if length(oclone1.Items[j].AsJSON) = 0 then
              strinsert := '""'
            else
              strinsert := oclone1.Items[j].AsJSON;
 
            //if strname = '3' then //ord_datum
            // strinsert:= ConvertDateFormat(strinsert);
 
            //strinsert := (strinsert);
 
            // Dieses zeichen \= ist in Bemerkungen
            strinsert := StringReplace(strinsert, ' \"', ' ', [rfReplaceAll]);
 
            sumstrinsert := sumstrinsert + ',' + strinsert;
          end;
        end;
 
        // komma = ',' am Anfang des strings entfernen
        sumstrinsert := copy(sumstrinsert, 2, length(sumstrinsert));
 
        //suminsert zum Gesamt SQL string hinzufügen
        sqlall := sqlall + '(' + sumstrinsert + ',"",""' + '),';
 
        sumstrinsert := '';
      end; // end for i
      sqlall := 'INSERT INTO orders VALUES ' + copy(sqlall, 1, Length(sqlall) - 1);
      try
        ZQOrdersInsert.SQL.Clear;
        ZQOrdersInsert.SQL.Text := sqlall;
        ZQOrdersInsert.ExecSQL;
        ZConnection1.Commit;
      except
        memo1.Lines.Add(sqlall);
      end;
    end; //for mit LS
  finally
    so.Free;
    Screen.Cursor := crDefault;
    Label2.Caption := datetimetostr(now, formatsettings);
    ZQOrdersDeleteAll.Active := False;
    ZQOrders.Refresh;
    ZQOrders.EnableControls;
    ProgressBar1.Position := 100;
    ProgressBar1.Visible := False;
    StatusBar1.Panels.Items[0].Text := '';
    StatusBar1.Panels.Items[2].Text := '';
    ZConnection1.AutoCommit := True;
    Application.ProcessMessages;
  end;
end;
 
P.S.
Die Begrenzungen für die SQL-Abfrage in ein Array zu schreiben, wär wahrscheinlich noch schneller. Ein paar Application.ProcessMessages weniger würden wahrscheinlich die Geschwindigkeit auch noch erhöhen. Muß mal probieren, aber 10 sec. für an die 1000 DS, das würde reichen.

Mir fällt nichts besser und Schnelleres ein.

Ciao

Josef

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6765
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: JSON Array in Datenbanktabelle

Beitrag von af0815 »

Kannst du mir noch die Defintion deiner Datenbanktabelle zukommen lassen ? Danke

Edit:
BTW: Im Verzeichnis LazausInstallDir/Tools/JSONViewer kann man sich den Viewer für JSON Dateien selbst erstellen. Siehe auch PDF-Artikel (Englisch) Webdata in XML und JSON.
Zuletzt geändert von af0815 am Sa 31. Okt 2015, 09:53, insgesamt 1-mal geändert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Hi,

hier die Tabellen Struktur.
sowohl die Internet Tabelle als auch die lokale Tabelle haben den gleichen Aufbau:

Code: Alles auswählen

 
CREATE TABLE [orders] (
  [ord_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
  [ord_forid] INTEGER, 
  [ord_datum] TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 
  [ord_firma] VARCHAR(50), 
  [ord_sel_anrede] VARCHAR(10), 
  [ord_vorname] VARCHAR(30), 
  [ord_nachname] VARCHAR(30), 
  [ord_strasse] VARCHAR(30), 
  [ord_plz] VARCHAR(8), 
  [ord_ort] VARCHAR(30), 
  [ord_land] VARCHAR(30), 
  [ord_telefon] VARCHAR(30), 
  [ord_fax] VARCHAR(30), 
  [ord_email] VARCHAR(130), 
  [ord_internet] VARCHAR(50), 
  [ord_lieffirma] VARCHAR(50), 
  [ord_liefsel_anrede] VARCHAR(10), 
  [ord_liefvorname] VARCHAR(30), 
  [ord_liefnachname] VARCHAR(30), 
  [ord_liefstrasse] VARCHAR(30), 
  [ord_liefplz] VARCHAR(8), 
  [ord_liefort] VARCHAR(30), 
  [ord_liefland] VARCHAR(30), 
  [ord_lieftelefon] VARCHAR(30), 
  [ord_lieffax] VARCHAR(30), 
  [ord_liefemail] VARCHAR(130), 
  [ord_liefinternet] VARCHAR(50), 
  [ord_bemerkung1] TEXT, 
  [ord_bemerkung2] TEXT, 
  [ord_bemerkung3] TEXT, 
  [ord_rabatt] FLOAT, 
  [AUFSKONTO] REAL DEFAULT '0', 
  [AUFLIEFVERWENDEN] INTEGER DEFAULT '0', 
  [AUFSTEUER] REAL DEFAULT '0', 
  [AUFSKONTOTAGE] INTEGER DEFAULT '0', 
  [AUFSTEUERVERWENDEN] INTEGER DEFAULT '0', 
  [AUFRABATTBETRAG] REAL DEFAULT '0', 
  [AUFZAHLFRISTEN] CHAR(120), 
  [ord_rabattverwenden] INTEGER, 
  [AUFSKONTOVERWENDEN] INTEGER DEFAULT '0', 
  [ord_versandkosten] FLOAT, 
  [AUFVERSANDART] VARCHAR(20), 
  [ord_bestellung] TEXT, 
  [ord_rechnung] TEXT, 
  [ord_vermerke] TEXT, 
  [ord_gesgewicht] FLOAT DEFAULT 0, 
  [ord_bemerkungen] TEXT, 
  [ord_status] INTEGER, 
  [ord_adresse] TEXT, 
  [ord_liefadresse] TEXT);
 
CREATE INDEX [orders_datumidx] ON [orders] ([ord_datum]);
 
Hier noch die Zeiten bei 975 Datensätzen und 50 Tabellenfeldern

Code: Alles auswählen

 
Start:: 31.10.2015 09:22:15
vor http:: 31.10.2015 09:22:15
vor Stringgrid: 31.10.2015 09:22:19
vor for Schleife: 31.10.2015 09:22:19
nach for Schleife: 31.10.2015 09:22:21
in finally end: 31.10.2015 09:22:21
 
Also insgesamt 6 sec.
Das JSON Array holen demnach 4 sec.
Das Kopieren des Array Inhalts in die Tabelle dauert 2 sec.

Soweit paßt es. Blöd ist nur die Aufteilerei in mehrere For-Schleifen und das Schreiben der entsprechenden For-Parameter in ein Stringgrid.

Wenn die ganze Operation in einem Rutsch liefe, wäre ein ganzer Schwung an Code weniger notwendig. Zeitlich fällt das Stringgridbefüllen nicht ins Gewicht.

Ciao

Josef

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6765
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: JSON Array in Datenbanktabelle

Beitrag von af0815 »

Liefert der Generator Daten, die so wie deine Strukturiert sind ? Damit ich deine Daten besser Analysieren kann.

Code: Alles auswählen

 
function GetDummyC:string;
begin
  Result := 'Dummy';
end;
 
function GetDummyI:string;
begin
  Result := IntToStr(99);
end;
 
function GetDummyF:string;
begin
  Result := FloatToStr(9.9);
end;
 
function GetDummyD:string;
begin
  Result := '1.1.2015';
end;
 
function GenerateData: String;
var
  JO,JLong : TJSONObject;
  i: Integer;
begin
  Result := '';
  JO := TJSonObject.Create;
//  JO.Add('ord_id', GetDummyC);
  JO.Add('ord_forid', GetDummyC);
  JO.Add('ord_datum', GetDummyD);
  JO.Add('ord_firma', GetDummyC);
  JO.Add('ord_sel_anrede', GetDummyC);
  JO.Add('ord_vorname', GetDummyC);
  JO.Add('ord_nachname', GetDummyC);
  JO.Add('ord_strasse', GetDummyC);
  JO.Add('ord_plz', GetDummyC);
  JO.Add('ord_ort', GetDummyC);
  JO.Add('ord_land', GetDummyC);
  JO.Add('ord_telefon', GetDummyC);
  JO.Add('ord_fax', GetDummyC);
  JO.Add('ord_email', GetDummyC);
  JO.Add('ord_internet', GetDummyC);
  JO.Add('ord_lieffirma', GetDummyC);
  JO.Add('ord_liefsel_anrede', GetDummyC);
  JO.Add('ord_liefvorname', GetDummyC);
  JO.Add('ord_liefnachname', GetDummyC);
  JO.Add('ord_liefstrasse', GetDummyC);
  JO.Add('ord_liefplz', GetDummyC);
  JO.Add('ord_liefort', GetDummyC);
  JO.Add('ord_liefland', GetDummyC);
  JO.Add('ord_lieftelefon', GetDummyC);
  JO.Add('ord_lieffax', GetDummyC);
  JO.Add('ord_liefemail', GetDummyC);
  JO.Add('ord_liefinternet', GetDummyC);
  JO.Add('ord_bemerkung1', GetDummyC);
  JO.Add('ord_bemerkung2', GetDummyC);
  JO.Add('ord_bemerkung3', GetDummyC);
  JO.Add('ord_rabatt', GetDummyF);
  JO.Add('AUFSKONTO', GetDummyF);
  JO.Add('AUFLIEFVERWENDEN', GetDummyI);
  JO.Add('AUFSTEUER', GetDummyF);
  JO.Add('AUFSKONTOTAGE', GetDummyI);
  JO.Add('AUFSTEUERVERWENDEN', GetDummyI);
  JO.Add('AUFRABATTBETRAG', GetDummyF);
  JO.Add('AUFZAHLFRISTEN', GetDummyC);
  JO.Add('ord_rabattverwenden', GetDummyI);
  JO.Add('AUFSKONTOVERWENDEN', GetDummyI);
  JO.Add('ord_versandkosten', GetDummyF);
  JO.Add('AUFVERSANDART', GetDummyC);
  JO.Add('ord_bestellung', GetDummyC);
  JO.Add('ord_rechnung', GetDummyC);
  JO.Add('ord_vermerke', GetDummyC);
  JO.Add('ord_gesgewicht', GetDummyF);
  JO.Add('ord_bemerkungen', GetDummyC);
  JO.Add('ord_status', GetDummyI);
  JO.Add('ord_adresse', GetDummyC);
  JO.Add('ord_liefadresse', GetDummyC);
  JLong := TJSonObject.Create;
  for i := 1 to 974 do
  begin
    JLong.Add('',JO.Clone);
  end;
  Result := JLong.AsJSON;
  JO.Free;
  JLong.Free;
end;
 
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Hallo,

Danke, daß du dich meines problems annimmst.

Also: Deine funktion läuft auch bei mir. Es werden schon brav alle JSON-Einträge in ein Memo-Feld geschrieben.

Hier der erste Eintrag:

Code: Alles auswählen

 
{ "" : { "ord_forid" : "Dummy", "ord_datum" : "1.1.2015", "ord_firma" : "Dummy", "ord_sel_anrede" : "Dummy", "ord_vorname" : "Dummy", "ord_nachname" : "Dummy", "ord_strasse" : "Dummy", "ord_plz" : "Dummy", "ord_ort" : "Dummy", "ord_land" : "Dummy", "ord_telefon" : "Dummy", "ord_fax" : "Dummy", "ord_email" : "Dummy", "ord_internet" : "Dummy", "ord_lieffirma" : "Dummy", "ord_liefsel_anrede" : "Dummy", "ord_liefvorname" : "Dummy", "ord_liefnachname" : "Dummy", "ord_liefstrasse" : "Dummy", "ord_liefplz" : "Dummy", "ord_liefort" : "Dummy", "ord_liefland" : "Dummy", "ord_lieftelefon" : "Dummy", "ord_lieffax" : "Dummy", "ord_liefemail" : "Dummy", "ord_liefinternet" : "Dummy", "ord_bemerkung1" : "Dummy", "ord_bemerkung2" : "Dummy", "ord_bemerkung3" : "Dummy", "ord_rabatt" : "9.9", "AUFSKONTO" : "9.9", "AUFLIEFVERWENDEN" : "99", "AUFSTEUER" : "9.9", "AUFSKONTOTAGE" : "99", "AUFSTEUERVERWENDEN" : "99", "AUFRABATTBETRAG" : "9.9", "AUFZAHLFRISTEN" : "Dummy", "ord_rabattverwenden" : "99", "AUFSKONTOVERWENDEN" : "99", "ord_versandkosten" : "9.9", "AUFVERSANDART" : "Dummy", "ord_bestellung" : "Dummy", "ord_rechnung" : "Dummy", "ord_vermerke" : "Dummy", "ord_gesgewicht" : "9.9", "ord_bemerkungen" : "Dummy", "ord_status" : "99", "ord_adresse" : "Dummy", "ord_liefadresse" : "Dummy" }, "" :.......
 
Das JSON Array war ja auch bei mir in Ordnung.

Nur eben die Array-Daten in eine Datenbanktabelle schreiben, da setzt es bei größer 500 Values aus.

Nochmal zur Verdeutlichung der Insert string:

Code: Alles auswählen

 
INSERT INTO orders VALUES ("136","1","2015-10-07 08:34:19.000","","Herr","Max","Schneider", usw....50 Felder),
          ("137","1","2015-10-11 12:45:11.000","Firma","Herr","Franz","Schuster", usw....50 Felder), 
                                          .....                                           
                                          usw. 
                                          IN meinem Fall wären es 975 dieser "Values-Klammern."      
 
Ich benutze nur Strings als Values zur Übergabe an die DB Tabelle. Ist bei SQLite auch kein Problem.

Danke dir nochmal.

Ciao

Josef

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6765
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: JSON Array in Datenbanktabelle

Beitrag von af0815 »

Es geht mir um die Testdaten. Mit der Routine kann ich mir beliebig große Datenmengen erzeugen. Das ist die Voraussetzung für eine vernünftige Optimierung.
Ein Snippet von deinen Json daten wäre zum Vergleich sinnvoll, damit die Struktur stimmt. Ich muss sagen, es ist mein erster Versuch mit Json.


Wenn die Daten so ok sind, kann ich zum Testen anfangen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

JosefKoller
Beiträge: 115
Registriert: Sa 17. Mär 2007, 10:53

Re: JSON Array in Datenbanktabelle

Beitrag von JosefKoller »

Hi,

hier der erste Eintrag:

Code: Alles auswählen

 
{"ord_id":"135","0":"135","ord_forid":"1","1":"1","ord_datum":"2013-09-22 13:49:40.000","2":"2013-09-22 13:49:40.000","ord_firma":"","3":"","ord_sel_anrede":"Herr","4":"Herr","ord_vorname":"Johannes","5":"Johannes","ord_nachname":"L\u00f6ffl","6":"L\u00f6ffl","ord_strasse":"Steinbockallee 41a","7":"Steinbockallee 41a","ord_plz":"0000","8":"0000","ord_ort":"XXX","9":"XXX","ord_land":"\u00d6sterrreich","10":"\u00d6sterrreich","ord_telefon":"+4367xxxxxxx","11":"+4367xxxxxxx","ord_fax":null,"12":null,"ord_email":"j.loeffl@gmx.at","13":"j.loeffl@gmx.at","ord_internet":null,"14":null,"ord_lieffirma":null,"15":null,"ord_liefsel_anrede":null,"16":null,"ord_liefvorname":null,"17":null,"ord_liefnachname":null,"18":null,"ord_liefstrasse":null,"19":null,"ord_liefplz":null,"20":null,"ord_liefort":null,"21":null,"ord_liefland":null,"22":null,"ord_lieftelefon":null,"23":null,"ord_lieffax":null,"24":null,"ord_liefemail":null,"25":null,"ord_liefinternet":null,"26":null,"ord_bemerkung1":"Ich h\u00e4tte die K\u00f6niginnen wenn m\u00f6glich gern zum fr\u00fchest m\u00f6glichen Versandtermin im Fr\u00fchjahr 2014.","27":"Ich h\u00e4tte die K\u00f6niginnen wenn m\u00f6glich gern zum fr\u00fchest m\u00f6glichen Versandtermin im Fr\u00fchjahr 2014.","ord_bemerkung2":null,"28":null,"ord_bemerkung3":null,"29":null,"ord_rabatt":null,"30":null,"AUFSKONTO":"0.0","31":"0.0","AUFLIEFVERWENDEN":"0","32":"0","AUFSTEUER":"0.0","33":"0.0","AUFSKONTOTAGE":"0","34":"0","AUFSTEUERVERWENDEN":"0","35":"0","AUFRABATTBETRAG":"0.0","36":"0.0","AUFZAHLFRISTEN":null,"37":null,"ord_rabattverwenden":null,"38":null,"AUFSKONTOVERWENDEN":"0","39":"0","ord_versandkosten":null,"40":null,"AUFVERSANDART":null,"41":null,"ord_bestellung":null,"42":null,"ord_rechnung":null,"43":null,"ord_vermerke":null,"44":null,"ord_gesgewicht":null,"45":null,"ord_bemerkungen":null,"46":null,"ord_status":"1","47":"1","ord_adresse":null,"48":null,"ord_liefadresse":null,"49":null},
 
Wie du siehst, sind die Einträge doppelt vorhanden. Einmal ord_id als Feldnamen und dann "0" als Feldnamen.
Deswegen auch meine Zeilen im Code:

Code: Alles auswählen

 
if Odd(j) then
          else
          begin ..... 
 
 
und null oder leer wird auf "" gesetzt.

Code: Alles auswählen

 
if oclone1.Items[j].AsJSON = 'null' then
              strinsert := '""'
            else
            if length(oclone1.Items[j].AsJSON) = 0 then
              strinsert := '""'
            else
              strinsert := oclone1.Items[j].AsJSON;     
 
Den Namen, die PLZ, den Ort, dieTelefonnummer und die Mailadresse hab ich abgeändert.

Ciao

Josef

Antworten