Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Datensätze schnell einfügen bzw. ersetzen (https://www.delphipraxis.net/180241-datensaetze-schnell-einfuegen-bzw-ersetzen.html)

messie 4. Mai 2014 11:49

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

Datensätze schnell einfügen bzw. ersetzen
 
Moin,

ich habe größere Datenmengen, die ich gerne schneller als bisher in eine Tabelle einfügen möchte.
Shmia hat so etwas hier beschrieben.
Bei mir kann es aber sein, dass die Daten schon vorhanden sind: vorhandene müssen überschrieben, neue angehängt werden. Kann man das als Einstellung mitgeben (z.B. "Insert or Replace")?

Grüße, Messie

DeddyH 4. Mai 2014 11:51

AW: Datensätze schnell einfügen bzw. ersetzen
 
UPDATE OR INSERT INTO

Sir Rufo 4. Mai 2014 11:53

AW: Datensätze schnell einfügen bzw. ersetzen
 
Suchst du sowas?
http://www.firebirdsql.org/refdocs/l...or-insert.html

@deddyH
:mrgreen: (kein roter Kasten)

mkinzler 4. Mai 2014 12:44

AW: Datensätze schnell einfügen bzw. ersetzen
 
Oder wenn man etwas flexibler reagiren will MERGE

Dejan Vu 4. Mai 2014 13:34

AW: Datensätze schnell einfügen bzw. ersetzen
 
Sind die Daten denn überhaupt schon in der Datenbank? Wenn Du auf shmia's Beitrag verweist, sieht das noch nicht so aus.

Tipp: Firebird kann sehr gut mit externen Tabellen im Textformat umgehen, eigentlich genauso wie mit einer Tabelle in der DB. Das, kombiniert mit den beiden Tipps, sollte deine Aufgabe optimal lösen.

messie 4. Mai 2014 15:40

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von Dejan Vu (Beitrag 1257886)
Sind die Daten denn überhaupt schon in der Datenbank? Wenn Du auf shmia's Beitrag verweist, sieht das noch nicht so aus.

Tipp: Firebird kann sehr gut mit externen Tabellen im Textformat umgehen, eigentlich genauso wie mit einer Tabelle in der DB. Das, kombiniert mit den beiden Tipps, sollte deine Aufgabe optimal lösen.

Moin,

das ist genau der Punkt: sie sind teilweise schon da. Daher die Fragestellung.

Ich meinte den Ansatz:
Code:
Query1.SQL.Text := 'SELECT * FROM '+tablename+' WHERE 0=1';
Query1.Open; // liefert ein leere Datenmenge

Query1.Append; // Einfügemodus
Query1['feld1'] := ...
Query1['feld2'] := ...
Query1.Post; // Daten abschicken
Der würde bei den vorhandenen Daten evtl. doppelte Datensätze erzeugen. Und da ist die Frage, ob man der Query ein Merge-Verhalten mit auf den Weg geben kann.
Das mit den Tabellen ist interessant. Wie bekomme ich die externe Tabelle in die DB (Beispiele, Tutorials?)

Grüße, Messie

mkinzler 4. Mai 2014 15:53

AW: Datensätze schnell einfügen bzw. ersetzen
 
Jein, man könnte aber die UpdateSQL-Eigenschaft oder die des Updateobjekts mit einem 'UPDATE OR INSERT INTO'-Statement belegen.
Zitat:

Das mit den Tabellen ist interessant. Wie bekomme ich die externe Tabelle in die DB (Beispiele, Tutorials?)
http://www.delphipraxis.net/1256882-post24.html

Sir Rufo 4. Mai 2014 15:55

AW: Datensätze schnell einfügen bzw. ersetzen
 
Und wir meinten den Ansatz
Delphi-Quellcode:
Query1.SQL.Text := 'UPDATE OR INSERT INTO table1 (Field1,Field2) VALUES (:Field1,:Field2)';
// das hier in einer Schleife ausführen
Query1.ParamByName('Field1').Value := ...
Query1.ParamByName('Field2').Value := ...
...
Query1.ExecSQL;
Etwas mehr Geschwindigkeit gibt es, wenn man sich die Parameter-Referenzen merkt, anstatt immer wieder durch
Delphi-Quellcode:
ParamByName
zu holen.

messie 4. Mai 2014 18:03

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von Sir Rufo (Beitrag 1257897)
Und wir meinten den Ansatz
Delphi-Quellcode:
Query1.SQL.Text := 'UPDATE OR INSERT INTO table1 (Field1,Field2) VALUES (:Field1,:Field2)';
// das hier in einer Schleife ausführen
Query1.ParamByName('Field1').Value := ...
Query1.ParamByName('Field2').Value := ...
...
Query1.ExecSQL;
Etwas mehr Geschwindigkeit gibt es, wenn man sich die Parameter-Referenzen merkt, anstatt immer wieder durch
Delphi-Quellcode:
ParamByName
zu holen.

Hm, bei dem Ansatz wird bemängelt, dass ich den primary key nicht mit übergebe. Ist das der DB_key? Den kenne ich zu dem Zeitpunkt evtl gar nicht, ebenso die ID falls sie schon da ist.

Grüße, Messie

Perlsau 4. Mai 2014 18:21

AW: Datensätze schnell einfügen bzw. ersetzen
 
Den Primary-Key setzt man gewöhnlich auf AutoInc und erzeugt den entsprechenden Key-Generator sowie die dazugehörige Stored Procedure nebst Trigger. Dann muß man ihn beim Insert nicht mitgeben. Im TIBCQuery stellt man dann das Property KeyFields auf den Primary Key und KeyGenerator auf den erzeugten Generator, damit der beim Insert aufgerufen wird und einen neuen Primary Key erzeugt und einträgt. Wenn du deine Tabelle mit IbExpert erzeugst, kannst du AutoInc, Generator, Procedure und Trigger automatisch erzeugen lassen.

Zeig doch mal deine Tabellenstruktur ...

messie 4. Mai 2014 19:18

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von Perlsau (Beitrag 1257909)
Den Primary-Key setzt man gewöhnlich auf AutoInc und erzeugt den entsprechenden Key-Generator sowie die dazugehörige Stored Procedure nebst Trigger. Dann muß man ihn beim Insert nicht mitgeben. Im TIBCQuery stellt man dann das Property KeyFields auf den Primary Key und KeyGenerator auf den erzeugten Generator, damit der beim Insert aufgerufen wird und einen neuen Primary Key erzeugt und einträgt. Wenn du deine Tabelle mit IbExpert erzeugst, kannst du AutoInc, Generator, Procedure und Trigger automatisch erzeugen lassen.

Zeig doch mal deine Tabellenstruktur ...

Moin,

meine Tabellenstruktur besteht im Wesentlichen aus 5 hierarchischen Tabellen die alle mit Trigger und Generatoren ausgestattet sind. Jede untergeordnete Tabelle trägt den Index der übergeordneten als Spalte.
Die Messdaten als unterste Hierarchie können verschiedene Messpunkte enthalten, daher habe ich bisher zu Fuß per Query geprüft, ob es zu den Abfragen schon einen Index gibt. Das ist sicher aber langsam.

Nachdem ich beim Lesen ein paar Sachen kapiert habe (vielfach-Join) würde ich gerne auch beim Schreiben Befehle zusammen fassen.

Was bedeutet Query.PrimaryKey und Query.KeyGenerator in diesem Zusammenhang?

Grüße, Messie

DeddyH 4. Mai 2014 19:30

AW: Datensätze schnell einfügen bzw. ersetzen
 
Leute, lest doch einfach die verlinkte Doku, insbesondere zur "MATCHING"-Klausel. Dort gibt man die Felder an, die als eindeutig anzusehen sind. Hat man einen Unique Key definiert, müssen mindestens dessen Felder hier angegeben werden.

Perlsau 4. Mai 2014 20:04

AW: Datensätze schnell einfügen bzw. ersetzen
 
In Query.PrimaryKey wählst du den Spaltennamen des Primary-Keys deiner Tabelle, damit die Komponente beim Insert weiß, wo sie hochzählen lassen muß. In KeyGenerator wählst du den entsprechenden Generator, damit deine Komponente weiß, wo sie den neuen Wert herbekommt.

Wäre es zuviel verlangt, einfach mal den Code deiner Tabellenstruktur hier zu posten? Sonst kann ich nicht erkennen, ob du nicht schon beim Erstellen der Tabelle bereits Fehler gemacht hast. Oder ist das geheim :?::stupid:

messie 12. Mai 2014 19:55

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von Perlsau (Beitrag 1257924)
Wäre es zuviel verlangt, einfach mal den Code deiner Tabellenstruktur hier zu posten? Sonst kann ich nicht erkennen, ob du nicht schon beim Erstellen der Tabelle bereits Fehler gemacht hast. Oder ist das geheim :?::stupid:

Ja, das ist geheim :oops: und nein, ich habe keine Fehler gemacht :stupid:

Ich habe nun den von mir bevorzugten Ansatz mal getestet und bekomme meine Änderungen tatsächlich zusätzlich als Eintrag in die entsprechende DB. Ein ganzer Haufen redundanter IDs :shock:
Aber es war sehr schnell trotz der großen Anzahl von Datensätzen :-D

Ich habe gelernt, dass ich in manchen Themen gerne mal völlig betriebsblind bin. Ich sehe bisher keine Möglichkeit, in einem Rutsch ein paar tausend Datensätze in ein paar Sekunden zu implantieren. Das ist aber eine Kernaufgabe die ich zu lösen habe.

Danke, Messie

jobo 12. Mai 2014 22:06

AW: Datensätze schnell einfügen bzw. ersetzen
 
Ein paar Gedanken dazu:

* Primärschlüssel, technische (automatisch generiert) helfen Dir nicht beim Existenzabgleich, denn die einzufügenden Daten besitzen diesen eindeutigen aber "zufälligen" Schlüssel nicht.

*"ein paar tausend Datensätze"
bekommst Du tatsächlich sehr schnell über externe Tabellen in die DB

* da empfiehlt sich ggF eine extra Importtabelle fürs Laden (alles rein, ohne Abgleich)

* im 2. Schritt dann die erwähnten Merges / Update or Insert Statements und zwar nicht Satz für Satz, sondern die komplette Zwischentabelle in einem Rutsch. Abgleich über fachliche Schlüsselfelder, ggf mehrere

messie 25. Mai 2014 08:47

AW: Datensätze schnell einfügen bzw. ersetzen
 
Moin,

ich habe jetzt eine Update or Insert-Liste erstellt wie vorgeschlagen. Ich scheitere derzeit aber an der Übergabe im Programm:
Code:
DM.Query2.SQL.Add('UPDATE OR INSERT INTO ' + MDATA + '(TIME_STAMP,PUMP_STEP_ID,MEASUREMENT_INDEX,MEASURED_VALUE,TIMESTAMP_VALUE) ' +
            'values(' + QuotedStr(TimeStamp) + ',' + QuotedStr(IntToStr(DBindex)) + ',' +
            QuotedStr(IntToStr(mid)) + ',' + QuotedStr(FormatFloatNow('#0.00000', MValues[mid])) + ',' +
            QuotedStr(ts) + ') matching (TIME_STAMP,PUMP_STEP_ID,MEASUREMENT_INDEX);' );
Wenn ich den Inhalt von SQL in eine Datei speichere und in Flamerobin einfüge klappt das ohne Probleme.
Was habe ich da übersehen?

Danke, Messie

Dejan Vu 25. Mai 2014 09:40

AW: Datensätze schnell einfügen bzw. ersetzen
 
Nimm doch erst einmal Parameter.

messie 25. Mai 2014 09:48

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von Dejan Vu (Beitrag 1260143)
Nimm doch erst einmal Parameter.

Moin,
verstehe ich nicht :oops:
Kann ich die returning-Klausel nicht weglassen? Was macht Flamerobin da anders?
Code:
update or insert into Cows (Name, Number, Location)
  values ('Suzy Creamcheese', 3278823, 'Green Pastures')
  matching (Number)
Grüße, Messie

mkinzler 25. Mai 2014 10:17

AW: Datensätze schnell einfügen bzw. ersetzen
 
Warum verwendet ihr immer .Add wenn ihr den Inhalt ersetzen wollt? :gruebel
Verwende besser (SQL-)Parameter!
Delphi-Quellcode:
DM.Query2.SQL.Text := 'UPDATE OR INSERT INTO ' + MDATA + '(TIME_STAMP,PUMP_STEP_ID,MEASUREMENT_INDEX,MEASURED_VALUE,TIMESTAMP_VALUE) ' +
            'values(':TIME_STAMP, :PUMP_STEP_ID, :MEASUREMENT_INDEX, :MEASURED_VALUE, :TIMESTAMP_VALUE);';
...
DM.Query2.ParamByName( 'TIME_STAMP).Value := TimeStamp;
...

messie 25. Mai 2014 10:47

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von mkinzler (Beitrag 1260147)
Warum verwendet ihr immer .Add wenn ihr den Inhalt ersetzen wollt? :gruebel
Verwende besser (SQL-)Parameter!
Delphi-Quellcode:
DM.Query2.SQL.Text := 'UPDATE OR INSERT INTO ' + MDATA + '(TIME_STAMP,PUMP_STEP_ID,MEASUREMENT_INDEX,MEASURED_VALUE,TIMESTAMP_VALUE) ' +
            'values(':TIME_STAMP, :PUMP_STEP_ID, :MEASUREMENT_INDEX, :MEASURED_VALUE, :TIMESTAMP_VALUE);';
...
DM.Query2.ParamByName( 'TIME_STAMP).Value := TimeStamp;
...

Add benutze ich weil ich ein paar tausend Werte ersetzen muss und das ExecSQL aus Geschwindigkeitsgründen nicht mit jeder Übergabe haben möchte. Nach meiner Auffassung und den obigen Beispielen muss ich doch nach jeder Übergabe das ExecSQL ausführen oder wird jede Parameterübergabe in den Cache geschrieben?
Was ist denn an meinem Statement falsch, dass es mit IBDAC nicht klappt aber in Flamerobin?

Grüße, Messie

Dejan Vu 25. Mai 2014 10:55

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von messie (Beitrag 1260153)
Was ist denn an meinem Statement falsch, dass es mit IBDAC nicht klappt aber in Flamerobin?

Geraten: Im Flamerobin ist eine andere Formatierung eingestellt (Datumsformat, Zahlen etc.) als in IBDAC. Daher der Rat, Parameter zu verwenden, denn dann werden die Werteformatierungen vom Provider vorgenommen, der vorher das RDBMS gefragt hat, wie die Parameter denn auszusehen haben.

mkinzler 25. Mai 2014 11:11

AW: Datensätze schnell einfügen bzw. ersetzen
 
Gerade dann bieten sich Parameter ja an. Die Abfrage brauchst du nur einmal setzen und dann nur noch die Parameter, es werden dann nur noch diese an das DBMS übertragen, Auch bei vollständigem Setzen der Abfrage musst sDu diese per ExecuteSQL senden.

messie 25. Mai 2014 11:54

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von Dejan Vu (Beitrag 1260155)
Zitat:

Zitat von messie (Beitrag 1260153)
Was ist denn an meinem Statement falsch, dass es mit IBDAC nicht klappt aber in Flamerobin?

Geraten: Im Flamerobin ist eine andere Formatierung eingestellt (Datumsformat, Zahlen etc.) als in IBDAC. Daher der Rat, Parameter zu verwenden, denn dann werden die Werteformatierungen vom Provider vorgenommen, der vorher das RDBMS gefragt hat, wie die Parameter denn auszusehen haben.

Nee, scheint am falschen Abschluss der Zeilen zu liegen. Einzeilige Befehle gehen ohne Fehler, bei mehrzeiligen Befehlen hakt es am Beginn der zweiten Spalte.

Allgemein habe ich noch nicht kapiert, wie ich mit den Parametern das matching ersetzen soll. Ich habe drei Parameter, aus denen sich ein Datensatz eindeutig erkennen lässt.
Eingentlich brauche ich dann mit Parametern doch auch ein matching oder liege ich da falsch?

Grüße, Messie

Edit: klappt gut mit dem matching aber ist ziemlich langsam trotz autocommit=false und cachedupdate=true.

jobo 25. Mai 2014 13:05

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von messie (Beitrag 1260162)
Nee, scheint am falschen Abschluss der Zeilen zu liegen. Einzeilige Befehle gehen ohne Fehler, bei mehrzeiligen Befehlen hakt es am Beginn der zweiten Spalte.

Ich kenne keine Clientkomponenten, mit denen mehrere Befehle als Script abgesetzt
werden können. Was nicht bedeutet, dass es sie nicht gibt.
Einziges mir bekanntes Verfahren ist die Verwendung eines anonymen Blocks, in dem (größenbeschränkt) mehrere Statements hintereinander verarbeitet werden können.
Das geht aber nur bei bestimmten RDBMS, die das unterstützen und Parameter zu verwenden wird schwierig.

Zitat:

Edit: klappt gut mit dem matching aber ist ziemlich langsam trotz autocommit=false und cachedupdate=true.
Wenn Du satzweise matching durchführst, muss das System für jeden Satz einzeln die gesamte Tabelle nach den Parametern scannen, ggF. mangels Index sogar per Fullscan.
Wenn es Dir zu langsam ist, prüf die Indizierung Deiner Parameter Spalten (Achtung Begriffe: Index<>Fremdschlüssel Constraint) oder schau Dir noch mal meinen Vorschlag an, alles in 2 Schritten zu machen.

messie 25. Mai 2014 13:08

AW: Datensätze schnell einfügen bzw. ersetzen
 
Moin,

das Update mit Parametern dauert jetzt eine halbe Stunde und ist erst zu einem Drittel fertig. Da muss wohl eine Tabellenlösung her.
@jobo: hast Du da ein etwas konkreteres Beispiel für mich?

Danke, Messie

jobo 25. Mai 2014 16:57

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von messie (Beitrag 1260165)
st erst zu einem Drittel fertig. Da muss wohl eine Tabellenlösung her.
@jobo: hast Du da ein etwas konkreteres Beispiel für mich?

"etwas konkreter" ist ja dehnbar. ;)

also hier mein Vorschlag von oben:
Zitat:

* da empfiehlt sich ggF eine extra Importtabelle fürs Laden (alles rein, ohne Abgleich)

* im 2. Schritt dann die erwähnten Merges / Update or Insert Statements und zwar nicht Satz für Satz, sondern die komplette Zwischentabelle in einem Rutsch. Abgleich über fachliche Schlüsselfelder, ggf mehrere
konkreter:
1. CSV Import über externes File wie z.B. hier nach Tabelle 'Neudat<en':
http://www.delphipraxis.net/180125-w...-firebird.html

2. korreliertes Update des Bestandes
über deine 3(?) Parameter
Code:
UPDATE Bestandsdaten
   SET <column> = N.<NewColumn>
            ..
   FROM bestandsdaten AS B INNER JOIN Neudaten As N
   On B.NR = N.NR ...
3. Delete der NeuDaten, die bereits für Update verwendet wurden.
Statement (vor allem Join) wie oben nur eben delete

4. Insert der Restdaten
Code:
insert into Bestandsdaten <columns>
select <columns> from Neudaten
5. Leeren der restlichen Neudaten
Code:
delete / truncate Neudaten
So mal als Idee. Kann man ausbauen oder abändern, wenn man mehr Kontrolle braucht.
z.B. "sind meine 3 Parameter eindeutig?", ...
Wenn man beim Bestand unsicher ist, ob die Kriterien hinreichend sind, kann man z.B. auf das Delete (Step3) verzichten, das Insert komplexer abgleichen und damit die gesamte Tabelle "Neudaten" für Prüfungen bewahren.
Ist man nicht sicher, dass die Eindeutigkeit der Neudaten über die gewünschten Kriterien gegeben ist, kann nach dem Import erstmal Prüfstatements drüberlaufen lassen.

messie 25. Mai 2014 17:22

AW: Datensätze schnell einfügen bzw. ersetzen
 
Moin,

ich habe das Problem jetzt aufgeteilt. Es gibt zwei Situationen, das nachträgliche händische Ändern von Messwerten und den Datenimport. Letzterer ist einmalig, also nicht ganz so wichtig. Da muss ich dann eben warten.
Bei den nachträglich geänderten Werten hole ich mit jetzt die Daten in eine Query und vergleiche den Messwert mit dem neuen Wert im Array. So muss ich nur auf der DB schreiben wenn sich die Werte tatsächlich geändert haben. Und da man in dieser Situation eher nur wenige Werte ändert, ist das kein Problem bei der Performance mehr.

Danke für die Unterstützung :thumb:

Grüße, Messie

messie 26. Mai 2014 17:28

AW: Datensätze schnell einfügen bzw. ersetzen
 
Ätsch, so schnell kann es gehen :oops:
Ich habe jetzt doch zwei andere Stellen wo ich ein paar tausend Datensätze auf einmal einfügen muss.
Daher zuerst die Frage für die Update or Insert-Variante: wie bekomme ich den vom Trigger angelegten Index des Datensatzes im returning zurück? Das Feld ID wird mir verweigert.

Grüße, Messie

mkinzler 26. Mai 2014 17:33

AW: Datensätze schnell einfügen bzw. ersetzen
 
Bei IBDAC wird dieser in dem Parameter RET_ID zurückgegeben.

messie 26. Mai 2014 17:51

AW: Datensätze schnell einfügen bzw. ersetzen
 
Zitat:

Zitat von mkinzler (Beitrag 1260331)
Bei IBDAC wird dieser in dem Parameter RET_ID zurückgegeben.

Danke!:thumb:

Noch ein komischer Fehler:
Code:
UPDATE OR INSERT INTO table (P_ID,ST_NO,MEASUREMENTS) VALUES(:P_ID,:ST_NO,:MEASUREMENTS) MATCHING (P_ID,ST_NO) returning RET_ID into :ID;
wirft mir einen Fehler "unexpected end of command line" an am Komma zwischen den beiden matching-Spalten. Ohne returning läuft es problemlos durch.

Grüße, Messie

Edit: wenn ich kürzere Variablen verwende, bleibt das Problem an derselben Spalte.

messie 26. Mai 2014 18:42

AW: Datensätze schnell einfügen bzw. ersetzen
 
Moin,

hat mal jemand ein funktionierendes Beispiel für ein Update od Insert mit einer matching und returning-Klausel?
Möglichst so, dass es auch im Flamerobin zu testen ist, denn das bekomme ich gerae nicht hin.
(Ich kann mir die angemessene Geduld heute nicht leisten, sorry)

Grüße, Messie

mkinzler 26. Mai 2014 19:27

AW: Datensätze schnell einfügen bzw. ersetzen
 
In MATCHING schreibst du die Liste der Felder die einen vorhandenen Datensatz identifizieren sollen in RETURNING das rückzulieferende Feld. Z.B. wenn eine Person anhand des Vornamens und Geburtsdatum identifiziert werden soll (Nachname kann sich ja ändern):

SQL-Code:
update or insert into Personen ( vorname, nachname, gebdat, ...) values ( 'Susi', 'Müller', '01.01.1990') MATCHING ( vorname, gebdat) RETURNING(ID);
-> 1

SQL-Code:
update or insert into Personen ( vorname, nachname, gebdat, ...) values ( 'Peter', 'Müller', '01.01.1990') MATCHING ( vorname, gebdat) RETURNING(ID);
-> 2


SQL-Code:
update or insert into Personen ( vorname, nachname, gebdat, ...) values ( 'Susi', 'Müller', '24.12.1974') MATCHING ( vorname, gebdat) RETURNING(ID);
-> 3


SQL-Code:
update or insert into Personen ( vorname, nachname, gebdat, ...) values ( 'Susi', 'Maier', '01.01.1990') MATCHING ( vorname, gebdat) RETURNING(ID);
-> 1

messie 26. Mai 2014 20:07

AW: Datensätze schnell einfügen bzw. ersetzen
 
Hallo Markus,

im Gegensatz zur OH schreibst du den returning-parameter in Klammern und ohne die into-Klausel. Das hilft gegen die merkwürdige Fehlermeldung "unexpected end of command line". Wenn ich dort "returning (RET_ID)" angebe, kann ich danach nicht darauf zugreifen. "ID" wird als nicht bekannt behandelt (obwohl als Spalte vorhanden), RET_ID wird in Klammern nicht als zulässige Spalte bezeichnet.
Hast Du eine korrekte Bezeichnung des Index' beim returning mit einer entsprechenden Abfrage?

Danke, Messie

mkinzler 26. Mai 2014 20:38

AW: Datensätze schnell einfügen bzw. ersetzen
 
Die Klammer ist falsch. Ich habe gerade kein Delphi zu Hand. Aber so sollte es gehen:

Delphi-Quellcode:
var
  sL, slF: TStrings;
  i: Integer;
...
begin
  try
    sl := TStringlist.Create;
    slf := TStringList.Create;
    slf.Delimiter := ';';
    sl.add( 'Susi'; 'Müller'; ...
    ..
    IBQuery.SQL.Text := 'update or insert into Personen ( vorname, nachname, gebdat) values ( :vorname, :nachname, :gebdat ) MATCHING ( vorname, gebdat) RETURNING id;';
    for i := 0 to sl.Count -1 do
    begin
      slf.DelimitedText := sl[i];
      IBQuery.Params[0].Value := slf[0];
      IBQuery.Params[1].Value := slf[1];
      IBQuery.Params[2].Value := slf[2];
      IBQuery.ExecSQL;
      id := IBQuery.Params[3].Value; //oder id := IBQuery.ParamByName('RET_ID').Value;
      ...
    end;
  finally
    slf.Free;
    sl.Free;
   ...
end;

messie 26. Mai 2014 21:07

AW: Datensätze schnell einfügen bzw. ersetzen
 
Hallo Markus,

bei mir klemmt es immer noch...
Kann evtl. jemand Anderes das mal testen?

Grüße, Ulfert

Zitat:

Zitat von mkinzler (Beitrag 1260348)
Die Klammer ist falsch. Ich habe gerade kein Delphi zu Hand. Aber so sollte es gehen:

Delphi-Quellcode:
var
  sL, slF: TStrings;
  i: Integer;
...
begin
  try
    sl := TStringlist.Create;
    slf := TStringList.Create;
    slf.Delimiter := ';';
    sl.add( 'Susi'; 'Müller'; ...
    ..
    IBQuery.SQL.Text := 'update or insert into Personen ( vorname, nachname, gebdat) values ( :vorname, :nachname, :gebdat ) MATCHING ( vorname, gebdat) RETURNING id;';
    for i := 0 to sl.Count -1 do
    begin
      slf.DelimitedText := sl[i];
      IBQuery.Params[0].Value := slf[0];
      IBQuery.Params[1].Value := slf[1];
      IBQuery.Params[2].Value := slf[2];
      IBQuery.ExecSQL;
      id := IBQuery.Params[3].Value; //oder id := IBQuery.ParamByName('RET_ID').Value;
      ...
    end;
  finally
    slf.Free;
    sl.Free;
   ...
end;


mkinzler 26. Mai 2014 21:08

AW: Datensätze schnell einfügen bzw. ersetzen
 
Wo klemmt es den genau?

mkinzler 27. Mai 2014 09:14

AW: Datensätze schnell einfügen bzw. ersetzen
 
Liste der Anhänge anzeigen (Anzahl: 4)
Ich habe es jetzt mal getestet, so funktioniert es in dem Testprogramm ( UniDAC statt IBDAC; aber UniDAC verwendet ja den IBDAC-Provider)

Delphi-Quellcode:
var
  sL, slF: TStrings;
  i, id: Integer;
begin
  try
    sl := TStringlist.Create;
    slf := TStringList.Create;
    slf.Delimiter := ';';
    sl.add( 'Susi;Mueller;01.01.1900');
    sl.add( 'Peter;Mueller;01.01.1990');
    sl.add( 'Susi;Mueller;24.12.1974');
    sl.add( 'Susi;Maier;01.01.1900');
    IBQuery.SQL.Text := 'update or insert into Person ( vorname, nachname, gebdat) values ( :vorname, :nachname, :gebdat ) MATCHING ( vorname, gebdat) RETURNING id;';
    for i := 0 to sl.Count -1 do
    begin
      slf.DelimitedText := sl[i];
      IBQuery.Params[0].Value := slf[0];
      IBQuery.Params[1].Value := slf[1];
      IBQuery.Params[2].asString := slf[2];
      IBQuery.ExecSQL;
      id := IBQuery.Params[3].Value; //oder id := IBQuery.ParamByName('RET_ID').Value;
      UniQuery1.Refresh;
      Application.ProcessMessages;
      ShowMessage( Format( 'Rückgabe: %d', [id]));
    end;
  finally
    slf.Free;
    sl.Free;
  end;
end;

messie 27. Mai 2014 16:17

AW: Datensätze schnell einfügen bzw. ersetzen
 
Moin,

jetzt funzt es bei mir auch. Ich glaube, ich sollte öfter mal den Rechner neu starten.
Ich habe ohnehin das Gefühl, dass Firebird sehr empfindlich auf Energiesparmodi ist.

Danke, Messie


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:20 Uhr.

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