AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken violation of FOREIGN KEY constraint
Thema durchsuchen
Ansicht
Themen-Optionen

violation of FOREIGN KEY constraint

Ein Thema von Zwirbel · begonnen am 16. Dez 2016 · letzter Beitrag vom 22. Dez 2016
Antwort Antwort
Seite 2 von 4     12 34      
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.733 Beiträge
 
Delphi 6 Enterprise
 
#11

AW: violation of FOREIGN KEY constraint

  Alt 16. Dez 2016, 08:59
Die spannendere Frage ist, wie würde denn ein solches SQL-Statement zum Bereinigen aussehen? Da ich wie gesagt von SQL noch nicht arg viel verstehe, kann mir da jemand möglichst etwas beispielhaftes zeigen? Danke, Gruß, Markus
Konkret müsste man dann im Einzelfall schauen, aber so ungefähr:

SQL-Code:
--Wenn man sich erstmal die betroffenen Datensätze angucken will
Select * From Detail_Tabelle
Where FK_Feld not in
(Select PK_Feld From Master_Tabelle)

--Wenn man's dann löschen will
Delete From Detail_Tabelle
Where FK_Feld not in
(Select PK_Feld From Master_Tabelle)
Das wäre jetzt für den Fall, das z.B. im Master sowas wie Aufträge sind, während in Detail die dazugehörigen Auftragspositionen stehen und wo es jetzt Auftragspositionen gibt, zu denen es im Master gar keine Aufträge gibt.
Ralph
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.270 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: violation of FOREIGN KEY constraint

  Alt 16. Dez 2016, 10:28
Hallo,
Paradox, die gute alte Zeit

Also ich würde vom SQL die Finger weglassen.
Sowas wie

Delete From DetailTable Where DetailTable.MasterId not In (Select MasterTable.MasterId From MasterTable)
dauert unter Paradox i.d.R. sehr lange.

Wenn du eh an alle Tabellen ranmusst:
Select DetailId,MasterId From DetailTable -> rein in eine TStringList DetailList
Select MasterTable.MasterId From MasterTable -> rein in eine TStringList MasterList

und jetzt alle Details durchlaufen und nach der MasterId in der MasterList suchen,
wenn nicht vorhanden, den Detailsatz löschen.
Heiko
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#13

AW: violation of FOREIGN KEY constraint

  Alt 16. Dez 2016, 10:51
Was ich hier aus dem Quelltext nicht ganz so genau entnehmen kann:
Delphi-Quellcode:
            InsertSQL := Format('INSERT INTO "%s" (%s) VALUES (%s)', [TableName, InsertFieldNames, InsertFieldValues]);
            qry_FB.SQL.Add(InsertSQL);
...
                { Nun die Werte je nach Datentyp übertragen von der Quelle ins Ziel }
                case tbl_Pdx.Fields[k].DataType of
                  ftString :
                    qry_FB.ParamByName(FieldNameUpper).AsString := tbl_Pdx.FieldByName(FieldNameMixed).AsString;
                  ftSmallint,
                  ftInteger,
                  ftWord,
                  ftAutoInc :
                    qry_FB.ParamByName(FieldNameUpper).AsInteger := tbl_Pdx.FieldByName(FieldNameMixed).AsInteger;
...
                qry_FB.ExecSQL(InsertSQL);
Werden die Daten satzweise übernommen?

Wenn ja, Methode einfach, billig und unelegant:
Delphi-Quellcode:
Try
  qry_FB.ExecSQL(InsertSQL);
except
  on e : Exception do begin
    // ggfls. Fehlertyp abfragen und Fehlermeldung in 'ne Logdatei schreiben.
  end;
end;
Wie greifts Du auf die Datenbanken zu, noch über die BDE?

Wenn ja, dann schau Dir (soweit in Deinem Delphi vorhanden) bitte einmal die Komponente TBatchMove an.

Da kann man einiges Konfigurieren:

Quelle und Ziel.
Feldmapping.
Verhalten im Fehlerfalle.
Ausgabetabelle für die Datensätze mit Schlüsselverletzungen.

Eventuell etwas Literatur zu der Komponente:

http://docwiki.embarcadero.com/RADSt...wenden_-_Index
http://edn.embarcadero.com/article/25620
http://docs.embarcadero.com/products...epart_xml.html

Ach, was mir noch einfiel:

Wird die BDE benutzt, so kann man in der Localsql.hlp nachlesen, was mit SQL möglich ist. Dazu gehören auch die "handelsüblichen" Joins.

Die Hilfedatei liegt gewöhnlich im gleichen Verzeichnis, wie BDEAdmin.exe.

Geändert von nahpets (16. Dez 2016 um 10:59 Uhr) Grund: Text ergänzt
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.733 Beiträge
 
Delphi 6 Enterprise
 
#14

AW: violation of FOREIGN KEY constraint

  Alt 16. Dez 2016, 11:31
Hallo,
Also ich würde vom SQL die Finger weglassen.
Sowas wie

Delete From DetailTable Where DetailTable.MasterId not In (Select MasterTable.MasterId From MasterTable)
dauert unter Paradox i.d.R. sehr lange.
Das war jetzt auch eher so gedacht, dass die Daten ohne Constraints, in die neue/modernere DB übertragen werden und da dann das SQL ausgeführt wird, bevor die Constraints dann aktiviert werden.

In Paradox/BDE würde ich sowas auch nicht machen wollen.
Ralph
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.270 Beiträge
 
Delphi 10.4 Sydney
 
#15

AW: violation of FOREIGN KEY constraint

  Alt 16. Dez 2016, 13:21
Hallo,
ah ja, das ginge.
Wobei die Geschwindigkeit dann trotzdem mau sein kann, wegen der fehlenden Indizes.

Also noch mal:
- DB ohne foreign keys (FKs) erzeugen.
- Daten rüberschaufeln.
- Datenleichen löschen
- FKs erzeugen.

In Firebird gibt es die Möglichkeit, eine Restore einer DB ohne aktivierte Indizes zu machen.
Danach muss man die aber afaik per Alter Index Active von Hand aktivieren.
Heiko
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#16

AW: violation of FOREIGN KEY constraint

  Alt 16. Dez 2016, 13:38
Wobei die Geschwindigkeit dann trotzdem mau sein kann, wegen der fehlenden Indizes.
Zum Einfügen braucht man keinen Index.

Praktische Erfahrung aus der Vergangenheit:

Daten ohne Index in die Datenbank schieben und anschließend Index erzeugen geht deutlich schneller, als Daten bei aktivem Index in die Datenbank zu schieben (vor allem bei großen Datenmengen).

Meiner Meinung nach:

Datenbank ohne Index
Datenbank ohne Constraints
Daten rein
Index erstellen
ggfls. bereinigen
Constrains erstellen

Was eventuell auch die eine oder andere Stunde sparen kann:

Aus den "alten" Daten Insertscripte als Datei(en) erstellen. Alle 1000 (oder so) Sätze ein Commit ins Script.

Scripte mit Datenbankmitteln einlesen (bei Oracle z. B. SQLLoader).

Index erstellen.
Bereinigen.
Constraints erstellen.

Wenn man Pech hat, muss man die letzten beiden Schritte wiederholen, bis alle Fehler behoben wurden.
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#17

AW: violation of FOREIGN KEY constraint

  Alt 16. Dez 2016, 13:42
Paradox könnte das können.
Der SQL Dialekt nennt sich "local SQL"
Hab auf die Schnelle das hier gefunden
http://www.ayton.id.au/gary/it/Delphi/C_sql01.htm

Irgendwo schwirren sicher auch die original HLP Files rum, die die Syntaxmöglichkeiten beschreiben.

Wenn eine gefilterte Abfrage mit konsistenten Daten (s.o.) nicht gelingt, sollte es doch sicher in der Zieldb gelingen, wie vorgeschlagen mit abgeschalteten FK Constraints.
Notfalls auch der Weg über Exception on Insert Error
(das kann natürlich auch andere Gründe haben und man muss die Fehlermeldung prüfen) bevor man die Insert Exception auf sich beruhen lässt.
Gruß, Jo
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.270 Beiträge
 
Delphi 10.4 Sydney
 
#18

AW: violation of FOREIGN KEY constraint

  Alt 17. Dez 2016, 06:27
Hallo,
mein SQL-Befehl von oben läuft ja.
Er ist halt nur langsam.

Vielleicht sollte man den beim Kunden auf einer Kopie der Datenbank mal laufen lassen.
Das Problem ist ja, daß man nie mit Echtdaten arbeiten kann.

fully populate your database

wie es so schön heißt ...
Heiko
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#19

AW: violation of FOREIGN KEY constraint

  Alt 17. Dez 2016, 09:58
mein SQL-Befehl von oben läuft ja.
Er ist halt nur langsam.
Welches SQL, das "Delete where not in"?

Diese Konstrukte sind in vielen DB nicht so dolle implementiert, erfahrungsgemäß, also gefühlt (ich habe natürlich noch nie eine solche Implementierung gesehen)
Viel versprechender ist es andersrum vorzugehen mittels eines Joins wie ihn DeddyH es hier
http://www.delphipraxis.net/1356311-post8.html
vorgeschlagen hat.

Es ist auch naheliegend, weil die Zeit nicht erst für Aufräumen "verschwendet" wird, sondern gleich die richtigen Daten selektiert werden. Also quasi "die guten ins Töpfchen, die schlechten .. " interessieren gar nicht.


Mal so nebenbei:
Ist Dir bekannt, dass die BDE heterogen arbeiten kann und Du sowas machen kannst*:
Code:
 insert into :firebirdtalias:desttable (f1,f2,f3)
SELECT
  Detail.*
FROM
  :bdetalias:Detail
  JOIN
    :bdetalias:Master ON Master.PK = Detail.FK
* Es sollte so gehen, ich hab hier nichts am Start, um das auszuprobieren.
Und es sollte halbwegs flott sein. Du brauchst natürlich einen BDE Alias auf die Zieldatenbank, vielleicht per ODBC, vlt. gibts auch einen nativen Treiber (Interbase?)


Grundsätzlich bei solchen Themen:
Je größer die Daten-Popelei** bei der Migration wird, desto eher gehe ich so vor.
Alle Altdaten werden in die Zieldatenbank übertragen, dort ist man idR flexibler (SQL) und schneller als mit dem veralteten Originalsystem.
Je nach Größe/Aufgabenstellung kann man das Verfahren dann abspecken / optimieren, natürlich vor allem dann, wenn es keine einmalige Sache ist, sondern auf mehreren Kundensystemen erfolgen soll.
Eine Variante des Vorgehens ist der vollständige Import der Altdaten in einen temporären Server mit identischer DB Installation. IdR kann man dann beim finalen Import im Zielsystem sehr bequem aus der Schwesterdb abfragen, also so halb heterogen.

** Popelei betrifft oft auch den Umbau von Feldinhalten. Dann spätestens sind wir beim Thema ETL (oder ELT), das geht wunderbar mit SQL und berechneten Feldern ohne meterlangen Programmcode. Dazu kann man auch schön Views nutzen, die die Transformation liefern. Kleine Fehler, die im Rahmen von Test auftauchen, sind schnell im View korrigiert ohne Programmcode zu ändern.
Natürlich gibt es auch super ETL tools, ist aber vielleicht für eine eigene Produktmigration nicht so der Knaller.
Gruß, Jo

Geändert von jobo (17. Dez 2016 um 10:27 Uhr)
  Mit Zitat antworten Zitat
Zwirbel

Registriert seit: 17. Aug 2009
64 Beiträge
 
Delphi 10 Seattle Ultimate
 
#20

AW: violation of FOREIGN KEY constraint

  Alt 20. Dez 2016, 08:56
Was ich hier aus dem Quelltext nicht ganz so genau entnehmen kann:
Delphi-Quellcode:
            InsertSQL := Format('INSERT INTO "%s" (%s) VALUES (%s)', [TableName, InsertFieldNames, InsertFieldValues]);
            qry_FB.SQL.Add(InsertSQL);
...
                { Nun die Werte je nach Datentyp übertragen von der Quelle ins Ziel }
                case tbl_Pdx.Fields[k].DataType of
                  ftString :
                    qry_FB.ParamByName(FieldNameUpper).AsString := tbl_Pdx.FieldByName(FieldNameMixed).AsString;
                  ftSmallint,
                  ftInteger,
                  ftWord,
                  ftAutoInc :
                    qry_FB.ParamByName(FieldNameUpper).AsInteger := tbl_Pdx.FieldByName(FieldNameMixed).AsInteger;
...
                qry_FB.ExecSQL(InsertSQL);
Werden die Daten satzweise übernommen?

Wenn ja, Methode einfach, billig und unelegant:
Delphi-Quellcode:
Try
  qry_FB.ExecSQL(InsertSQL);
except
  on e : Exception do begin
    // ggfls. Fehlertyp abfragen und Fehlermeldung in 'ne Logdatei schreiben.
  end;
end;
Ja, die Daten werden datensatzweise übertragen. Genau so (Exception abfangen) habe ich es jetzt erst mal gemacht.

Zitat:
Wie greifts Du auf die Datenbanken zu, noch über die BDE?
Ja, habe mir diese alten BDE-Komponenten für Delphi Seattle geholt. Der Versuch über ODBC zuzugreifen und damit die BDE aus der Migrations-Applikation heraus zu halten scheitert daran, dass wir ausschließlich Paradox Tabellen im 7er Format einsetzen und das geht über ODBC nicht.

Wir haben uns jetzt dafür entschieden erst mal keine weitere Zeit in eine Optimierung zu investieren. Zum Glück haben wir von fast allen Kunden Echtdaten hier und haben so zumindest schon mal einen Überblick wo es überall haken kann und notfalls schalte ich diese derzeit zeitintensiven Reparaturroutinen per Option in der Migrations-Applikation ein.

Danke an alle für die vielfältigen und hilfreichen Informationen. Gruß, Markus
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:43 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