![]() |
Datenbank: MSSQL • Version: server • Zugriff über: ADO
Beim Einlesen doppelte Datensätze (PK) verhindern
Hallo zusammen,
ich möchte eine CSV Datei einlesen, Felder (EAN = Primary Key), Art-Nr usw.. Das Einlesen klappt wunderbar. Bis es zu einer Primary Key Verletzung kommt, dadurch wird das weitere Einlesen verhindert ! Wie kann ich nun dem Programm sagen, das es bei soch einer Konstellation diesen Satz überspringen soll und mit dem nächsten Datensatz der CSV weitermachen soll ?
Delphi-Quellcode:
:roll: Grüße vom nachtstreuner
while memo1.Lines.Count <> i do begin
sTEXT := memo1.Lines[i]; Liste := EXPLODE(';',sTEXT); // Daten Speichern IF (sTEXT <> '') and (LISTE[0] <> 'EAN_NR') then begin // SATZ_SPEICHERN; // with ADOQueryMetro do begin if AdoConnectionMetro.Connected = false then begin try AdoConnectionMetro.ConnectionString := ProvString; //'Provider=SQLOLEDB.1;Password=Eisenach09!;Persist Security Info=True;'+ // 'User ID=sa;Initial Catalog=METRO;Data Source=METROSQL\SQLEXPRESS'; AdoConnectionMetro.Connected := true; AdoQueryMetro.Active := true; except on E : Exception do begin MELDUNG := 'VERBINDUNGSFEHLER : '+ E.Message; writelog; FEHLER := 1; application.Terminate; form1.Close; ABORT; EXIT; end; end; end; //Showmessage('Kein Fehler'); // weiter //Showmessage(Liste[0]); try ADOQueryMetro.SQL.Clear; ADOQueryMetro.SQL.Text := 'INSERT into PRODUKTE (EAN_NR, ART_BEZ_ALTERN, '+ 'PWHG, PWG, PWUG, KZ_WERB) '+ 'VALUES (:sEAN_NR, :sART_BEZ_ALTERN, :sPWHG, :sPWG, :sPWUG, :sKZ_WERB)'; ADOQueryMETRO.Parameters.ParamByName('sEAN_NR').Value := LISTE[0]; ADOQueryMETRO.Parameters.ParamByName('sART_BEZ_ALTERN').Value := LISTE[5]; ADOQueryMETRO.Parameters.ParamByName('sPWHG').Value := LISTE[7]; ADOQueryMETRO.Parameters.ParamByName('sPWG').Value := LISTE[8]; ADOQueryMETRO.Parameters.ParamByName('sPWUG').Value := LISTE[9]; ADOQueryMETRO.Parameters.ParamByName('sKZ_WERB').Value := LISTE[10]; //------------------------ ADOQueryMETRO.ExecSQL; except on E : Exception do begin MELDUNG := 'Doppelter Datensatz(EAN) : ' + LISTE[0] +' | ' +E.Message; Showmessage(MELDUNG); writelog; end; end; end; end; i := i +1; // memo1.Lines.Delete(0); end; MELDUNG := 'Es wurden ['+ IntToStr(i) + '] Zeilen verarbeitet...'; WRITELOG; |
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Würde sich ja ein Merge anbieten
|
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Hier erst mal ein paar Tipps:
1.) bitte den Code, der die Verbindung zur Datenbank herstellt in eine eigene Methode verschieben.
Delphi-Quellcode:
Diese Methode wird einmal VOR der Schleife aufgerufen
procedure TForm1.ConnectToDatabase;
begin if not AdoConnectionMetro.Connected then begin AdoConnectionMetro.ConnectionString := ProvString; //'Provider=SQLOLEDB.1;Password=Eisenach09!;Persist Security Info=True;'+ // 'User ID=sa;Initial Catalog=METRO;Data Source=METROSQL\SQLEXPRESS'; AdoConnectionMetro.Connected := true; end; end; 2.) Das SQL für die Query wird ebenfalls nur einmal vor der Schleife aufrufen
Delphi-Quellcode:
3.) Du fängst ja schon Fehler beim Einfügen mittels try..except ab.
ADOQueryMetro.SQL.Text := 'INSERT into PRODUKTE (EAN_NR, ART_BEZ_ALTERN, '+
'PWHG, PWG, PWUG, KZ_WERB) '+ 'VALUES (:sEAN_NR, :sART_BEZ_ALTERN, :sPWHG, :sPWG, :sPWUG, :sKZ_WERB)'; Nur bringt das wenig, wenn du die Fehlermeldung mit ShowMessage() gleich anzeigst. Stellt dir vor, es sind 100 doppelte Datensätze in der CSV-Datei - viel Spass beim OK-klicken.8-) 4.) die Zeile
Delphi-Quellcode:
komplett löschen. Bei einem SQL-Insert macht dies keinen Sinn; es stört eher.
AdoQueryMetro.Active := true;
|
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Viele Dank erstmal für die Antworten,
mit dem MERGE muss ich mich erstmal beschäftigen. Die Tips von shmia habe ich beherzigt und auch so im unten stehenden Code eingefügt : Allerdings schreibt er mir jetzt keinen einzigen Datensatz in die DB, Stattdessen erhalte ich folgende Meldung aus dem Protokoll : 02.09.2010 18:59:08 Es werden [15668] Zeilen verarbeitet ! 02.09.2010 18:59:18 Doppelter Datensatz(EAN) : 1215126156152 | Ungültige Autorisierungsangabe 02.09.2010 18:59:24 Doppelter Datensatz(EAN) : 1233567891012 | Ungültige Autorisierungsangabe 02.09.2010 18:59:29 Doppelter Datensatz(EAN) : 1234567890128 | Ungültige Autorisierungsangabe 02.09.2010 18:59:36 Doppelter Datensatz(EAN) : 1472583691477 | Ungültige Autorisierungsangabe und das obwohl ich vor dem Start die Tabelle geleert habe. Hier nochmal der geänderte Code :
Code:
:pale:
//==============================================================================
// Verbindung zur Datenbank herstellen //============================================================================== procedure TForm1.ConnectToDatabase; begin if not AdoConnectionMetro.Connected then begin AdoConnectionMetro.ConnectionString := ProvString; //'Provider=SQLOLEDB.1;Password=*******;Persist Security Info=True;'+ // 'User ID=sa;Initial Catalog=METRO;Data Source=METROSQL\SQLEXPRESS'; try AdoConnectionMetro.Connected := true; // ADOQueryMETRO.Active := true; except on E : Exception do begin MELDUNG := 'VERBINDUNGSFEHLER : '+ E.Message; writelog; FEHLER := 1; application.Terminate; form1.Close; ABORT; EXIT; end; end; end; end; //============================================================================== // Verarbeitung starten //============================================================================== procedure TForm1.Button1Click(Sender: TObject); var i : integer; liste : TStringDynArray; sTEXT,DATNAME : string; test : variant; begin try memo1.Clear; memo1.Lines.LoadFromFile(FILEPFAD +'\'+ FileDat); MELDUNG := FilePFAD + '\' + FileDat + ' ... eingelesen'; WRITELOG; except MELDUNG := '[FEHLER:] Konnte CSV Datei nicht öffnen ...'; WRITELOG; Application.Terminate; end; I := 0; MELDUNG := 'Es werden ['+IntToStr(memo1.Lines.Count)+'] Zeilen verarbeitet !'; Writelog; ADOQueryMetro.SQL.Clear; ADOQueryMetro.SQL.Text := 'INSERT into PRODUKTE (EAN_NR, ART_BEZ_ALTERN, '+ 'PWHG, PWG, PWUG, KZ_WERB) '+ //, WERB_ID, WERB_ZEITR_VON, WERB_ZEITR_BIS, '+ //'BAS_GROESSE, UWD_MASSENEINHEIT_SL, VK_PREIS_BR, VK_PREIS_ALT_BR, '+ //'VK_PREIS_WERB_BR, GRUNDPREIS_BR, GRUNDPREIS_ALT_BR, GRUNDPREIS_WERB_BR, '+ //'AKTIONSBEGINN, AKTIONSENDE) ' + 'VALUES (:sEAN_NR, :sART_BEZ_ALTERN, :sPWHG, :sPWG, :sPWUG, :sKZ_WERB)'; while memo1.Lines.Count <> i do begin sTEXT := memo1.Lines[i]; Liste := EXPLODE(';',sTEXT); // Daten Speichern IF (sTEXT <> '') and (LISTE[0] <> 'EAN_NR') then begin // SATZ_SPEICHERN; // ADOQueryMETRO.Parameters.ParamByName('sEAN_NR').Value := LISTE[0]; ADOQueryMETRO.Parameters.ParamByName('sART_BEZ_ALTERN').Value := LISTE[5]; ADOQueryMETRO.Parameters.ParamByName('sPWHG').Value := LISTE[7]; ADOQueryMETRO.Parameters.ParamByName('sPWG').Value := LISTE[8]; ADOQueryMETRO.Parameters.ParamByName('sPWUG').Value := LISTE[9]; ADOQueryMETRO.Parameters.ParamByName('sKZ_WERB').Value := LISTE[10]; //------------------------ try ADOQueryMETRO.ExecSQL; except on E : Exception do begin MELDUNG := 'Doppelter Datensatz(EAN) : ' + LISTE[0] +' | ' +E.Message; Showmessage(MELDUNG); writelog; end; end end; i := i +1; // memo1.Lines.Delete(0); end; MELDUNG := 'Es wurden ['+ IntToStr(i) + '] Zeilen verarbeitet...'; WRITELOG; DATNAME := leftstr(dateToStr(date),2)+midstr(dateToStr(date),4,2)+ leftstr(TimeToStr(time),2)+midstr(timeToStr(time),4,2)+ midstr(timeToStr(time),7,2)+'.CSV'; // movefile(PChar(FILEPFAD+ '\' + FileDat),PChar(sichPFAD+'\'+DATNAME)); MELDUNG := FILEPFAD + '\' + FileDat+' nach '+ sichPfad + '\'+DATNAME+' verschoben !!'; //frmLOGBUCH.memo.Lines.Add('c:\wa_order.txt nach c:\sich_order\'+DATNAME+' verschoben !!'); writelog; MELDUNG := 'VERARBEITUNG abgeschlossen !! - Keine FEHLER !'; WRITELOG; //Form1.close; end; |
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Wo rufst du denn deine Connect-Procedure auf?
|
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Hallo Rapante,
in der ersten Procedure im String 'ProvString' Der connect funktioniert ja, sonst hätte ich dort schon eine Fehlermeldung bekommen. :? |
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Hallo Rapante,
das war von mir eine Falschmeldung !!! Habe ganz übersehen, nach dem füllen des Strings 'ProvString' die Prozedur ConnectToDatabas aufzurufen. Jetzt funktiniert zumindest das wegschreiben in die Tabelle. In der CSV Datei die ich einlese, befindet sich eine doppelte EAN-Nummer, dieses wird in der Tabelle in das Primary Key Feld EAN_NR geschrieben, nach 50000 Datensätzen bekomme ich dann die Fehlermeldung [Window Title] Metro [Content] Doppelter Datensatz(EAN) : 3073780993654 | Verletzung der PRIMARY KEY-Einschränkung 'PK__PRODUKTE__3A831F4D7F60ED59'. Ein doppelter Schlüssel kann in das dbo.PRODUKTE-Objekt nicht eingefügt werden [OK] Da das Einlesen später autom. ohne Benutzerreaktion nachts eingelesen werden soll, frage ich mich, wie ich diese Fehlermeldung abfangen kann, den doppelten EAN-Code(Satz) überspringe und mit dem nächsten Satz weitermache... |
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Lass doch einfach das showmessage weg und schreib stattdessen die Fehlermeldung in dein Logfile.
|
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Ich würde entweder alle EAN in eine Liste schreiben (IntegerList) und prüfen, ob sie dort bereits existiert
ODER Vor dem INSERT mit "COUNT * .... WHERE EAN = ...." prüfen, ob Datensätze mit der EAN vorhanden sind |
AW: Beim Einlesen doppelte Datensätze (PK) verhindern
Danke an alle für Eure Tips,
ich habe es jetzt so gemacht wie Rapante vorgeschlagen hat, SHowmessage ausschalten und stattdessen den doppelten EAN-code in das Logfile eintragen, da hat man gleich noch einen Nachweis für den Ersteller der CSV datei, aus diesen Info´s kann er dann Massnahmen ergreifen, um doppelte EAN Codes zu vermeiden. Nachdem Einlesen wird also ein Mail generiert und an den Lieferanten der CSV zurückgeschickt, dieser kann sie dann bearbeiten. Danke nochmal an alle. Problem gelöst und dies wie immer sehr schnell. mfg nachtstreuner |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz