AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Beim Einlesen doppelte Datensätze (PK) verhindern
Thema durchsuchen
Ansicht
Themen-Optionen

Beim Einlesen doppelte Datensätze (PK) verhindern

Ein Thema von nachtstreuner · begonnen am 2. Sep 2010 · letzter Beitrag vom 2. Sep 2010
Antwort Antwort
nachtstreuner

Registriert seit: 21. Aug 2005
Ort: ESA
104 Beiträge
 
Delphi XE2 Professional
 
#1

Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 17:01
Datenbank: MSSQL • Version: server • Zugriff über: ADO
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:
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;
Grüße vom nachtstreuner
Alles wird gut -

Geändert von mkinzler ( 2. Sep 2010 um 17:04 Uhr) Grund: Code-Tag durch Delphi-Tag ersetzt
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 17:05
Würde sich ja ein Merge anbieten
Markus Kinzler
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#3

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 17:19
Hier erst mal ein paar Tipps:
1.) bitte den Code, der die Verbindung zur Datenbank herstellt in eine eigene Methode verschieben.
Delphi-Quellcode:
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;
Diese Methode wird einmal VOR der Schleife aufgerufen
2.) Das SQL für die Query wird ebenfalls nur einmal vor der Schleife aufrufen
Delphi-Quellcode:
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)';
3.) Du fängst ja schon Fehler beim Einfügen mittels try..except ab.
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.

4.) die Zeile AdoQueryMetro.Active := true; komplett löschen. Bei einem SQL-Insert macht dies keinen Sinn; es stört eher.
Andreas
  Mit Zitat antworten Zitat
nachtstreuner

Registriert seit: 21. Aug 2005
Ort: ESA
104 Beiträge
 
Delphi XE2 Professional
 
#4

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 18:58
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:
//==============================================================================
// 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;
Alles wird gut -
  Mit Zitat antworten Zitat
Benutzerbild von rapante
rapante

Registriert seit: 3. Jun 2009
Ort: OPR
172 Beiträge
 
Delphi 12 Athens
 
#5

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 19:19
Wo rufst du denn deine Connect-Procedure auf?
Micha
  Mit Zitat antworten Zitat
nachtstreuner

Registriert seit: 21. Aug 2005
Ort: ESA
104 Beiträge
 
Delphi XE2 Professional
 
#6

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 19:48
Hallo Rapante,

in der ersten Procedure im String 'ProvString'

Der connect funktioniert ja, sonst hätte ich dort schon eine Fehlermeldung bekommen.

Alles wird gut -
  Mit Zitat antworten Zitat
nachtstreuner

Registriert seit: 21. Aug 2005
Ort: ESA
104 Beiträge
 
Delphi XE2 Professional
 
#7

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 19:57
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...
Alles wird gut -
  Mit Zitat antworten Zitat
Benutzerbild von rapante
rapante

Registriert seit: 3. Jun 2009
Ort: OPR
172 Beiträge
 
Delphi 12 Athens
 
#8

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 20:11
Lass doch einfach das showmessage weg und schreib stattdessen die Fehlermeldung in dein Logfile.
Micha
  Mit Zitat antworten Zitat
Benutzerbild von scrat1979
scrat1979

Registriert seit: 12. Jan 2007
Ort: Sulzbach a.d. Murr
1.028 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 20:14
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
Michael Kübler
  Mit Zitat antworten Zitat
nachtstreuner

Registriert seit: 21. Aug 2005
Ort: ESA
104 Beiträge
 
Delphi XE2 Professional
 
#10

AW: Beim Einlesen doppelte Datensätze (PK) verhindern

  Alt 2. Sep 2010, 22:05
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
Alles wird gut -
  Mit Zitat antworten Zitat
Antwort Antwort


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 00:05 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