Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   TFDBatchMove mit AutoInc (https://www.delphipraxis.net/212113-tfdbatchmove-mit-autoinc.html)

TurboMagic 20. Dez 2022 15:46

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

TFDBatchMove mit AutoInc
 
Hallo,

gegeben ein Delphi 11.2, eine Firebird Datenbank mit Tabellen die per
Generator automatisch erzeugte eindeutige Primärschlüssel haben und
jemanden der mit FDBatchMove noch nichts gemacht hat.

Wunsch: Kopieren von solchen Datensätzen in eine andere Datenbank.
Dort ist ja auf der gleichnamigen Tabelle aber auch ein Generator drauf.

Geht sowas? Wie kann man mit sowas umgehen?
Und was, wenn das Ziel nicht eine andere DB ist, sondern die selbe Tabelle?
Ich also nur eine Kopie eines Datensatzes machen will? Kann ich beim BatchMove
also Spalten aussparen? (wäre auch für nicht zu kopierende Spalten interessant)
Also sowas wie * aber ohne "Spalte4" und "Spalte7", so dass ich nicht alle zu
kopierenden Spalten angeben muss, was bei Strukturänderungen doof wäre.

Grüße
TurboMagic

Olli73 20. Dez 2022 16:03

AW: TFDBatchMove mit AutoInc
 
Ist das Autoinc_feld so angelegt:

create table t1 (id integer generated by default as identity primary key)

oder via Trigger + Generator?

Wie sieht im zweiten Fall der Trigger aus?

TurboMagic 20. Dez 2022 17:49

AW: TFDBatchMove mit AutoInc
 
Pwer Trigger und Generator.
Trigger sieht so aus:

Delphi-Quellcode:
CREATE TRIGGER BI_KASSE_BONKOPF_BON_ID FOR KASSE_BONKOPF
ACTIVE BEFORE
  INSERT
POSITION 0
AS
BEGIN
  IF (NEW.BON_ID IS NULL) THEN
      NEW.BON_ID = GEN_ID(KASSE_BONKOPF_BON_ID_GEN, 1);
END^
Grüße
TurboMagic

Olli73 20. Dez 2022 18:13

AW: TFDBatchMove mit AutoInc
 
Wenn du immer einen neuen Key haben willst musst du entweder das Feld nicht übergeben, Null übergeben oder den Trigger so ändern, dass er nicht auf Null prüft.

TurboMagic 20. Dez 2022 18:58

AW: TFDBatchMove mit AutoInc
 
Danke schon Mal dafür.
Nur: wie kann ich beim Batch Move Spalten ausblenden?

Uwe Raabe 20. Dez 2022 20:14

AW: TFDBatchMove mit AutoInc
 
Wenn das ID-Feld in der Zieltabelle als Identity markiert ist, sollte es reichen das poIdentityInsert aus den BatchMove-Options zu entfernen:
Zitat:

When this option is selected, then insert/update of the destination identity columns is enabled.

TurboMagic 21. Dez 2022 17:23

AW: TFDBatchMove mit AutoInc
 
Hallo,

bin noch ganz neu bei der BatchMove Komponente.
Was bedeutet Zielfeld? Muss ich da irgendwie angeben in welche Spalten die Quelldaten sollen?
Wenn die den selben Namen wie die Quellspalten doch wohl eher nicht, oder?

Uwe Raabe 21. Dez 2022 21:39

AW: TFDBatchMove mit AutoInc
 
Das ist korrekt. Wenn Name, Typ und Size übereinstimmen sollte das problemlos funktionieren.

Mit den ID-Feldern ist das aber etwas tricky. Im Idealfall erkennt FireDAC solche Felder automatisch und entfernt das pfUpdate in den ProviderFlags. Damit wird das Feld nicht in die DB geschrieben. Mit dem Entfernen des oben genannten poIdentityInsert wird genau das ausgenutzt.

Näheres zu solchen ID-Feldern und deren Erkennung findest du hier: Auto-Incremental Fields

TurboMagic 21. Dez 2022 21:54

AW: TFDBatchMove mit AutoInc
 
Danke schon mal dafür, nur hab' ich ja noch ein Problem:
Ich muss auch ein paar der Spalten-Werte vor dem Schreiben negieren (* -1).
Das scheint so nicht wirklich machbar, zumidnest nicht was ich bisher so in
den Eigenschaften der Komponenten gesehen habe.

=> vermutlich muss ich's doch "klassisch" umsetzen.

Delphi.Narium 22. Dez 2022 10:11

AW: TFDBatchMove mit AutoInc
 
Zitat:

Zitat von TurboMagic (Beitrag 1516533)
Ich muss auch ein paar der Spalten-Werte vor dem Schreiben negieren (* -1).

Daten per BatchMove übernehmen und dann ein
SQL-Code:
update tabelle set spalte = spalte * -1
hinterherschicken?

Uwe Raabe 22. Dez 2022 10:29

AW: TFDBatchMove mit AutoInc
 
Zitat:

Zitat von TurboMagic (Beitrag 1516533)
Ich muss auch ein paar der Spalten-Werte vor dem Schreiben negieren (* -1).


Delphi-Quellcode:
TBatchMove.OnWriteValue
:
Zitat:

The OnWriteValue event is triggered before a source value will be moved to target data source. The AItem argument identifies data item (eg, dataset field). The AValue argument represent the item value. An application may use this event to reformat or convert the source value.

TurboMagic 22. Dez 2022 19:12

AW: TFDBatchMove mit AutoInc
 
Halloo,

danke für den Hinweis, beim versuch da was drauß zu machen bin ich aber an einer anderen Stelle hängen geblieben.

Gegeben:

Delphi-Quellcode:
var
  FQueryReadKasseBonkopf : TFDBatchMoveSQLReader;
  FBatchMoveBonKopf     : TFDBatchMove;
begin
  FQueryReadKasseBonkopf  := TFDBatchMoveSQLReader.Create(nil);
  FBatchMoveBonKopf       := TFDBatchMove.Create(nil);
  FBatchMoveBonKopf.Reader := FQueryReadKasseBonkopf;

  FQueryReadKasseBonkopf.ReadSQL :=
    'select KASSE_ID, BON_TYP, BON_NAME, BON_START, BON_ENDE, UMS_BRUTTO, ' +
    '      KUNDE_TYP, KUNDE_ID ' +
    'from KASSE_BONKOPF where BON_NR = :pBonNr';

  FQueryReadKasseBonkopf.FDDataSet.ParamByName('pBonNr').AsInteger := 123;
  FBatchMoveBonKopf.Execute;
Beim Ausführen der vorletzten Zeile kracht es mit "Parameter pBonNr" nicht gefunden.
Warum?

Natürlich ist das nicht alles so in einer Methode oder so, also Vorschläge direkt
das SQL anzupassen sind nicht wirklich zielführend.

Uwe Raabe 22. Dez 2022 21:07

AW: TFDBatchMove mit AutoInc
 
Das ReadSQL wird erst beim Open dem SQL des DataSets zugewiesen. Daher ist der Parameter zu dem Zeitpunkt noch nicht bekannt. In dem Fall wäre es vielleicht besser einen TFDBatchMoveDataSetReader und eine TFDQuery zu verwenden. TFDBatchMoveSQLReader unterstützt leider keine Parameter, sondern nur plain SQL.

TurboMagic 23. Dez 2022 11:13

AW: TFDBatchMove mit AutoInc
 
So, mit den Hinweisen bin ich einen halben Schritt weiter, nur kracht es jetzt anderweitig.

First chance exception at $7720E292. Exception class EIBNativeException with message
'[FireDAC][Phys][FB]validation error for column "MEINE_TABELLE"."MEINE_SPALTE", value "*** null ***"'. Process MeineExe.exe (6728)

Naja, diese MEINE_SPALTE existiert in der Quell und Zieltabelle, weil beide dieselbe Tabelle in der selben DB sind.
Diese ist als Nicht Null definiert, aber mit einem Default Value 0 und wird im SQL zum lesen des zu kopierenden Datensatzes
nicht mit ausgelesen, weil der Inhalt nicht kopiert werden soll.

Warum versucht da jetzt jemand NULL reinzuschreiben, statt einfach den Default Wert zu benutzen?
Wie kann ich das verhindern/ändern?

Die Optiones der BatchMove instance sehen übrigens so aus:
[poSkipUnmatchedDestFields];

Grüße
TurboMagic

himitsu 23. Dez 2022 12:07

AW: TFDBatchMove mit AutoInc
 
Wenn im INSERT das explizit als NULL zugewiesen wird, dann wird der DEFAULT nicht benutzt. Der wird nur verwendet, wenn diese Spalte garnicht übergeben wurde.

Bei manchen DBMS kann man auch im INSERT das Keyword DEFAULT als Wert angeben, wenn man diese Spalte unbedingt mit übergeben will/muß. (z.B. beim BatchImport/MultiInsert)
Notfalls könntest du im Batch-Script eventuell einfach alle NULL durch DEFAULT ersetzen.
(aber k.A. ob Firebird das auch so kennt)


Zitat:

poSkipUnmatchedDestFields
Eventuell ein Bug?
Aber sollte poSkipUnmatchedDestFields nicht nur "nichtvorhandene" Felder weglassen?
Bei dir existiert sie auf beiden Seiten, also ist sie somit matched (nicht unmatched).

TurboMagic 23. Dez 2022 12:31

AW: TFDBatchMove mit AutoInc
 
Danke mal dafür, nur: im SQL Statement für das Lesen steht diese Spalte ja gar nicht drin, ist also als Quelle nicht vorhanden
und der Writer für den BatchMove erzeuge ich zwar, gebe dem aber kein SQL vor. Das soll er sich ja selber zusammen bauen.

=> was nun?

Ich neige gerade dazu das wieder alles händisch ohne BatchMove zu machen, aber eigentlich wollte ich an der Stelle auch mal
das BatchMove ausprobieren... :-(

Olli73 23. Dez 2022 12:33

AW: TFDBatchMove mit AutoInc
 
Hast du irgendwo UpdateOptions als Eigenschaft?

Dann setz dort mal CheckRequired auf false (FireDAC.Stan.Option.TFDUpdateOptions.CheckRequire d).

TurboMagic 23. Dez 2022 12:56

AW: TFDBatchMove mit AutoInc
 
Hallo,

so eine Eigenschaft hab' ich nicht wirklich gefunden auer an der DB-Connection,
das ist aber nicht was du suchtest.

Der Write für die FDBatchMove Instanz ist ein TFDBatckMoveSQLWriter und da gibt's
sowas auch nicht. Die Options die der hat sind etwas anders gelagert...

Grüße
TurboMagic

Olli73 23. Dez 2022 13:00

AW: TFDBatchMove mit AutoInc
 
Wir nutzen das auch nur bei TfdQuery. Aber ich würde mal das bei der Connection probieren...

TurboMagic 23. Dez 2022 13:13

AW: TFDBatchMove mit AutoInc
 
Zitat:

Zitat von Olli73 (Beitrag 1516626)
Wir nutzen das auch nur bei TfdQuery. Aber ich würde mal das bei der Connection probieren...

Hab' ich eben, kracht aber leider genauso... :-(
Also immer noch die Frage wem ich in dem Szenario wie sagen kann, dass er diese Spalten in Ruhe lassen soll...
Passende QP reports hab' ich dazu auch nicht gefunden.

Olli73 23. Dez 2022 14:12

AW: TFDBatchMove mit AutoInc
 
TFDBatchMoveSQLWriter.FDDataSet.UpdateOptions.Chec kRequired ?

TurboMagic 23. Dez 2022 14:15

AW: TFDBatchMove mit AutoInc
 
Noch ein anderes Problem mit dem Ansatz:
wenn ich mal eines Tages diesen Datensatz tatsächlich kopiert bekomme, hat ja der Generator für den
primary key in dieser Tabelle dem neuen Satz einen neuen Wert generiert.

Nur wie bekomme ich den zurückgeliefert?
Ja, ich könnte einfach mittels select nach dem höchsten Datensatz fragen, aber wenn dann mal später
evtl. mehrere Leute auf die selbe DB zugreifen wird's schnell haarig...

TurboMagic 23. Dez 2022 14:17

AW: TFDBatchMove mit AutoInc
 
Zitat:

Zitat von Olli73 (Beitrag 1516630)
TFDBatchMoveSQLWriter.FDDataSet.UpdateOptions.Chec kRequired ?

Hallo,

eben erst gesehen, gleich getestet, gleich enttäuscht worden. :-(
Sorry!

Grüße

TurboMagic

Olli73 23. Dez 2022 14:22

AW: TFDBatchMove mit AutoInc
 
Dann musst du wohl mittels TBatchMove.OnWriteValue die Nulls zu Defaulftwert machen...

Aber bei TFDQuery klappt das mit chekRequired bei mir super. Bei mir war das Problem aber auch nicht ein Defaultwert, sondern die Vergabe der ID durch die DB.

TurboMagic 23. Dez 2022 14:47

AW: TFDBatchMove mit AutoInc
 
Hallo,

oh ich... ;-)
Ich bin einen Schritt weiter: ich hatte ja schon ein Event im Writer in dem ich für bestimmte Spalten
Werte vor dem Schreiben ändern bzw. setzen wollte. Auch für die Spalte die jetzt immer Ärger gemacht hatte.
Nur: dazu muss diese Spalte natürlich beim Reader im Select drin stehen! :oops: :wall:

Also zumindest für die Tabelle komme ich damit schon mal weiter.

Grüße
TurboMagic

Uwe Raabe 23. Dez 2022 16:29

AW: TFDBatchMove mit AutoInc
 
Die Connection muss den Parameter ExtendedMetaData auf True setzen, damit FireDAC den Default-Wert erkennt.

TurboMagic 23. Dez 2022 16:38

AW: TFDBatchMove mit AutoInc
 
Danke für den Hinweis!

TurboMagic 23. Dez 2022 17:16

AW: TFDBatchMove mit AutoInc
 
Tja, nur knallt es mit ExtendedMetadata jetzt woanders.
Da will ich per FieldByName(..).AsInteger den Wert einer als Smallint definrten Spalte
abrufen und bekomme eine Exception geworfen, dass er diese Spalte nicht als Integer abrufen kann.
Aber Smallint passt doch da rein und .AsSmallInt gibt's ja nicht...

Was nun?

himitsu 23. Dez 2022 17:24

AW: TFDBatchMove mit AutoInc
 
Das .AsXyz ist dem egal.

Ihm geht es um den Typ des Feldes,
also TSmallintField statt TIntegerField. :zwinker:

Hast du die Felder selbst erstellt, oder lässt du Sie erstellen?

TurboMagic 23. Dez 2022 17:30

AW: TFDBatchMove mit AutoInc
 
Ich hab' nix selbst erstellt. Einfach eine FDQuery und der einen select als SQL gesetzt...

himitsu 23. Dez 2022 17:33

AW: TFDBatchMove mit AutoInc
 
Dann sollte es ja eigentlich schon stimmen.
Was sagt denn FieldByName(..).ClassName ?

TurboMagic 23. Dez 2022 17:37

AW: TFDBatchMove mit AutoInc
 
TBooleanField. Als das ist's genau genommen sogar intendiert, nur: woher weiß er das?
Und das müsste ich ja dann jetzt überall umstellen...

himitsu 23. Dez 2022 17:59

AW: TFDBatchMove mit AutoInc
 
Zitat:

Woher?
Rate mal, wofür die Meta-Data da sind. :wink:

Zusatzinfos zu den Feldern: Originaler Name, bei mit AS imbenannt, QuellTabellenname, der genaue Typ, das Default uvm.

TurboMagic 23. Dez 2022 18:01

AW: TFDBatchMove mit AutoInc
 
Moment! Ich hab nirgends gesagt, dass das Boolean sein soll. Woher leitet der sich das ab?

himitsu 23. Dez 2022 18:24

AW: TFDBatchMove mit AutoInc
 
Achso, klang irgendwie so, als wenn es "eigentlich" so sei. (in der DB)

Nja, das DBMS sagt der Übertragung (Treiber) was es ist, im Delphi kommt es als was an (meistens Integer/Enum) und dann gibt es z.B. eine Übersetzungstabelle von DB-ÜbertragungsTyp zu Delphi-Typ (TFieldType/TDataType) und dann nochmal eine Übersetzung zur TField-Ableitung.
Eventuell nochmal spezielle Anpassungen z.B. am Typename aus den ExtendedInfos.
Und man kann die Zuordnung auch nochmal selbst überschreiben. (z.B. wenn es Probleme gibt, oder man es anders braucht)

Uwe Raabe 23. Dez 2022 18:42

AW: TFDBatchMove mit AutoInc
 
Wie heißt denn die Domain für die SmallInt Spalte?

Zitat:

Q3: How can I force FireDAC to recognize some field as boolean?
A: A boolean field may be created using a domain. The domain name must contain 'BOOL' substring. Also, add ExtendedMetadata=True parameter to your connection definition. For example:

CREATE DOMAIN T_BOOLEAN SMALLINT;
CREATE TABLE ... (
...
BOOLEAN_FIELD T_BOOLEAN,
...);

TurboMagic 23. Dez 2022 20:35

AW: TFDBatchMove mit AutoInc
 
Ok, die hat "Boolean" mit im DOmain Namen. Das erklärt jetzt das.

himitsu 23. Dez 2022 20:54

AW: TFDBatchMove mit AutoInc
 
Zitat:

Eventuell nochmal spezielle Anpassungen z.B. am Typename aus den ExtendedInfos.
Ohne ExtraInfos kommt nur der interne Typ bei raus
und Mit weiß FD nun, dass es eigentlich ein Boolean ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:18 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