ADODB Problem

Hallo,

mit unten stehendem Code habe ich ein Problem.

Das Programm soll Daten aus einer Textdatei in eine MDB eintragen. Die Textdatei wird geändert, erweitert. Neue Daten sollen eingetragen werden, dabei habe ich Probleme mit den Daten, die schon eingetragen sind.

Die Funktion ‚Suche‘ soll feststellen, ob ein Datensatz in der Datenbank bereits vorhanden ist und wenn der Datensatz noch nicht existiert, soll er eingetragen werden.

Manchmal verläuft die Suche negativ, der Datensatz wird nach meinem Verständnis also nicht gefunden. Wenn er angelegt werden soll kommt dann eine Fehlermeldung, daß eine Schlüsselverletzung vorliegt, der Datensatz kann nicht angelegt werden. Der Fehler ist nicht abfangbar, das Programm steigt aus.

Kann Jemand meinen Fehler sehen? Was ich nicht verstehe: Das Programm läuft auch mal mehrere Tage ohne Fehler durch, bis es hängen bleibt.

Oder habe ich etwas übersehen und es gibt einen einfacheren Weg? Das Ziel ist, daß ein mal täglich der Inhalt der MDB an den Inhalt der Textdatei angepasst wird. Es kommen etwa 20 bis 30 Datensätze neu dazu.

Gruß, Rainer

 If suche(EDVNr, cha) = False Then
 RS.AddNew
 RS("EDVnummer") = EDVNr
 RS("Chargennummer") = cha
 RS("Lieferantenkurznummer") = lknr
 RS.Update
 End If


Private Function suche(ByVal EDVNr As String, ByVal cha As String) As Boolean
 Dim DB As String
 DB = "c:\Datenbank.mdb"
 strSQL = "SELECT \* " & \_
 "FROM Chargen " & \_
 "WHERE (EDVNummer = '" & EDVNr & "') And (Chargennummer = '" & cha & "');"
 Set objConnection = New ADODB.Connection

 With objConnection
 .CursorLocation = adUseClient
 .Mode = adModeShareDenyNone
 .Provider = "Microsoft.Jet.OLEDB.4.0"
 .ConnectionString = DB
 .Open
 End With

 Set objRS = New ADODB.Recordset
 With objRS
 Set .ActiveConnection = objConnection
 .CursorLocation = adUseClient
 .CursorType = adOpenStatic
 .LockType = adLockOptimistic
 .Source = strSQL
 Call .Open
 End With

 If objRS.RecordCount = 0 Then
 suche = False
 Else
 suche = True
 End If
 objRS.Close
End Function

Hallo Rainer,

eine Idee:

So wie dein Code aussieht, mit dem du einen neuen Datensatz erzeugst, scheint eine Zeile nur über alle drei Parameter eindeutig. Soweit ich das in ACCESS beurteilen kann, kann man nur eine Spalte zum Primärschlüssel deklarieren. Damit führen gleiche „EDVnummer“, sofern das der Primärschlüssel ist, zu inkonsistenzen. Eigentlich soll man mehrere P-Sch vereinbaren können, aber ich kriege das nicht hin!

Abhilfe könnte eine Spalte ID bringen, in der du einen echten P-Sch einträgst:

 If suche(EDVNr, cha) = False Then
 RS.AddNew
 'hoffe das & stimmt!
 RS("id") = EDVNr & cha & lknr
 RS("EDVnummer") = EDVNr
 RS("Chargennummer") = cha
 RS("Lieferantenkurznummer") = lknr
 RS.Update
 End If

mfg

Dirk.Pegasus

Hallo Dirk,

So wie dein Code aussieht, mit dem du einen neuen Datensatz
erzeugst, scheint eine Zeile nur über alle drei Parameter
eindeutig.

Das stimmt, aber parktisch genügen zwei, weil die verschiedenen Lieferanten verschiedene Systeme für die Chargenbezeichnungen verwenden. Der selbe Chargenschlüssel kann für verschiedene Lieferanten nicht auftauchen. Das sieht man dem Code natürlich nicht an, das konntest Du unmöglich wissen, sorry daß ich das nicht schon geschrieben hatte.

Soweit ich das in ACCESS beurteilen kann, kann man
nur eine Spalte zum Primärschlüssel deklarieren.

Nein, ich habe teilweise Schlüssel, die aus sieben Feldern bestehen, das kann Access.

Damit führen
gleiche „EDVnummer“, sofern das der Primärschlüssel ist, zu
inkonsistenzen.

Das ist richtig, der Primärschlüssel besteht aus EDVNummer und Charge. Hoffe ich. :smile: Starte ich das Programm neu, hängt das Programm dann auch an einer anderen Stelle, es gibt Datensätze mit gleicher EDV-Nummer und unterschiedlicher Charge. Ich habe auf meinem Rechner Access97 und kann die Datenbank nicht mit Access lesen. :frowning: Ich brauche Access97 aber für andere Projekte unbedingt und ich kann nicht zwei Versionen von Access gleichzeitig installieren.

Eigentlich soll man mehrere P-Sch vereinbaren
können, aber ich kriege das nicht hin!

Primärschlüssel kann es nur einen geben. Du meinst einen aus mehreren Feldern? ‚Strg‘ halten und klicken. :smile:

Abhilfe könnte eine Spalte ID bringen, in der du einen echten
P-Sch einträgst:

Die Datenbank kann ich nicht ändern, ist nicht ‚meine‘, ich versorge sie nur mit Daten … b.z.w. ich versuche es. :smile: (Der Pfad im Beispiel ist gefaked, die Datenbank liegt auf einem Server im Rechnezentrum) Ursprünglich lief das mit DAO und da ohne Probleme. Seit der Umstellung auf ADO bringt mich die Datenbank zur Verzweiflung. :frowning:

Danke für die Hilfe!

Gruß, Rainer

Hallo Rainer,

versuch mal folgendes:

 strSQL = "SELECT \* " & \_
 "FROM Chargen " & \_ 
 "WHERE (UCase(EDVNummer) like 'UCase(" & EDVNr & ")') \_
 And (UCase(Chargennummer) like 'UCase(" & cha & ")');"

Anstelle = ein like, das mE „unempfindlicher“ ist und zur Vorsicht alles in Großbuchstaben.

Wie sieht es denn beim Debuggen aus? Hast du die Feldinhalte der „verdächtigen“ mal in einem Editor verglichen?

Ach und vielen Dank: Ja, man kann mehrere Felder als Primärschlüssel festlegen, wenn man weiss wie …

mfg

Dirk.Pegasus

1 Like

Nachsatz
Hallo Rainer,

ggfs. mal im SQL Brett fragen, da sind doch spezis, und ob die sich hierher verlaufen … (:wink:)

mfg

Dirk.Pegasus

Hallo Dirk,

versuch mal folgendes:

strSQL = "SELECT * " & _
"FROM Chargen " & _
„WHERE (UCase(EDVNummer) like 'UCase(“ & EDVNr &
„)’) _
And (UCase(Chargennummer) like 'UCase(“ & cha &
„)’);“

Anstelle = ein like, das mE „unempfindlicher“ ist und zur
Vorsicht alles in Großbuchstaben.

Danke, werde ich tun. Beim letzten Versuch ist das Programm durchgelaufen, nun muß ich erst auf neue Daten warten um zu sehen, ob es wieder Probleme gibt. Das Programm läuft im produktiven Einsatz, da ist es immer ärgerlich, wenn dann etwas verändert wird und sich das Testen so mühsam gestaltet. Zusatzinfo: Das Programm versorgt unsere Waage mit Auftragsdaten und der Information, welches Material von welchem Hersteller für den Auftrag eingesetzt wurde.

Wie sieht es denn beim Debuggen aus? Hast du die Feldinhalte
der „verdächtigen“ mal in einem Editor verglichen?

Ich habe keinen. :frowning: Ich kann die Datenbank nur mit meinem VB-Programm lesen, mein Access97 kann die Datenbank nicht lesen, die ist wohl mit Access2003 geschrieben. Nach einer Fehlermeldung steht der Datensatz dann ja auch tatsächlich in der Datenbank. Ob er vorher auch schon da ist, ist schwer zu sagen, ich habe einige Tausend Datensätze sowohl in der Quelle als auch in der MDB, die zum größten Teil identisch sind.

Inzwischen habe ich für die Verbindung, mit der ich Daten schreibe mal ein ‚Refresh‘ in den Code eingefügt, danach lief das Programm durch. Nun ist es zwar noch langsamer als vorher, aber es startet täglich um 22.00 Uhr, läuft im Moment etwa 10 Minuten und ist damit lange vor der Datensicherung um 01.00 Uhr fertig, das genügt mir.

Ich erzähle dann übermorgen, ob noch ein Fehler auftritt.

Danke für die Hilfe! Wenn ich allein vor einem Problem sitze und keine Ahnung habe, wie ich es lösen soll, gehen mir die Ideen aus. Wenn wir darüber sprechen und ich habe Hilfe, kommen auch die Ideen wieder. :smile:

Gruß, Rainer

Hi Dirk,

ggfs. mal im SQL Brett fragen, da sind doch spezis, und ob die
sich hierher verlaufen … (:wink:)

mit SQL komme ich recht gut zurecht, notfalls kann ich Schulungsunterlagen zu Rate ziehen. Vor zwei Jahren hatte ich mal einen SQL-Lehrgang an der Uni … da könnte ich also ohne weiteres mal Fragen beantworten. :smile:

Gruß, Rainer

Hallo Rainer,
ich wollte gar nicht stören,
der Code sieht soweit OK aus, aber kann es sein, dass die DB in sich bspw. einen DS einfügt, in sich noch keinen Commit abgesetzt hat und beim nächsten DS findet der SELECT dadurch nichts aber der INSERT bricht ab weil eben der Key schon da ist?

Gruß
Klaus

Hallo Klaus,

ich wollte gar nicht stören,

stören? :smile: Ich habe doch um Hilfe gebeten, da ist jeder Kommentar zum Thema recht!

der Code sieht soweit OK aus, aber kann es sein, dass die DB
in sich bspw. einen DS einfügt, in sich noch keinen Commit
abgesetzt hat

Bis hier her verstehe ich das nicht so ganz richtig.

und beim nächsten DS findet der SELECT dadurch
nichts aber der INSERT bricht ab weil eben der Key schon da
ist?

Das beschreibt mein Problem wohl. Ich hatte angenommen, daß ich immer den tatsächlichen Inhalt bekomme, weil ich ja das Recordset jedesmal neu aufbaue. Offensichtlich ist der Datensatz schon vorhanden, wird aber trotzdem nicht ‚gesehen‘. Wenn meine verschwommene Vorstellung von dem, was Du oben schreibst richtig ist, dann ist das Problem durch das ‚Refresh‘, das ich inzwischen eingebaut habe tatsächlich gelöst. Besonders schön ist das aber trotzdem nicht, weil das Programm davon sehr viel langsamer wird.

Gruß, Rainer

Ich habe mal ein ähnliches Problem bei INSERT gehabt, habs damit gelöst, dass ich nach dem INSERT so lange SELECTS auf die neuen Inhalte gemacht habe, bis der SELECT nicht mehr fehlgeschlagen ist …
Aber das Problem bei Dir sollte sein:
Du verarbeitest eine neue Datei und da machst Du neue INSERTS,
Du solltest demnach vorher die Datei auf „Doppelte Einträge“ durchsuchen …

Gruß
Klaus

Hallo Klaus,

Ich habe mal ein ähnliches Problem bei INSERT gehabt, habs
damit gelöst, dass ich nach dem INSERT so lange SELECTS auf
die neuen Inhalte gemacht habe, bis der SELECT nicht mehr
fehlgeschlagen ist …

hmmm. Tatsächlich vorhandene Datensätze werden gefunden, wenn ich es richtig sehe, tritt das Problem mit Datensäten auf, die beim Programmstart noch nicht in der Datenbank stehen.

Aber das Problem bei Dir sollte sein:
Du verarbeitest eine neue Datei und da machst Du neue INSERTS,
Du solltest demnach vorher die Datei auf „Doppelte Einträge“
durchsuchen …

Die Daten kommen aus einer Indexsequentiellen Datenbank mit eindeutigem Schlüssel, da kann es keine doppelten Datensätze geben.
Warum ich das dann so umständlich mache? Die Daten kommen aus einer alten Informix-Datenbank auf einem SCO Open Server 5.0 Rechner. Einen ODBC-Treiber für die Datenbank gibt es nicht. Deshalb stelle ich die Daten mit einem Programm als Textdatei zur Verfügung und zerlege den Text dann wieder in seine Bestandteile und übertrage die in die .mdb.

Gruß, Rainer
PS. Im Moment scheint es zu laufen, keine Fehlermeldung! :smile:

Hallo Rainer,

Jede Datenbank, und dajede Tabelle sollte ein Feld ID haben vom Typ Autoincrement. So verhindert man das indentische Eintraege vorhanden sind. Sollte die DB nicht so ein Feld haben, so würde ich das schnellstens ändern.

Aber nungut. Zu deinem Problem :wink:

Ich frage jetzt mal ganz blöd. Bei deiner Abfrage

strSQL = "SELECT \*FROM Chargen WHERE (EDVNummer = '" & EDVNr & "') And (Chargennummer = '" & cha & "');"

wurde da jemals ein Datensatz gefunden?
Ich daechte das du bei einen Vergleich auf ein String die ’ nur in Verbindung mit LIKE verwenden darfst. Aber nicht wenn du ein Vergleich mit = startest. So dürftest du nie einen Datensatz finden!
Ist nun aber der Datensatz vorhanden und du bekommst Fals zurueck und versuchst einen neuen Datensatz anzulegen, naja den Rest weisst du selber!

Suchkriterium = Alexander

…LIKE ‚Alexander‘ ->Sucht nach der Zeichenfolge Alexander
…=‚Alexander‘ ->Sucht nach der Zeichenfolge ‚Alexander‘
…=Alexander -> Sucht nach der Zeichenfolge Alexander

Dann mal was anderes. In deiner Function Suche wo du dann true oder false zuweisst, warum machst dasso umstaendlich?

suche=cbool(rs.Recordcount\>0)

MfG Alex

Hallo Alex,

Jede Datenbank, und dajede Tabelle sollte ein Feld ID haben
vom Typ Autoincrement. So verhindert man das indentische
Eintraege vorhanden sind. Sollte die DB nicht so ein Feld
haben, so würde ich das schnellstens ändern.

an der Datenbank kann ich nichts ändern. Das ist nicht ‚meine‘, ich versorge sie nur.

Ich frage jetzt mal ganz blöd. Bei deiner Abfrage

strSQL = „SELECT *FROM Chargen WHERE (EDVNummer = '“ & EDVNr &
„’) And (Chargennummer = '“ & cha & „’);“

wurde da jemals ein Datensatz gefunden?

Ja.

Ich daechte das du bei einen Vergleich auf ein String die ’
nur in Verbindung mit LIKE verwenden darfst. Aber nicht wenn
du ein Vergleich mit = startest. So dürftest du nie einen
Datensatz finden!

Doch, geht. Das System ist im produktiven Einsatz, wenn das nie klappen würde, hätte unsere Waage keine Daten und ich keinen Job mehr. :smile:

Ist nun aber der Datensatz vorhanden und du bekommst Fals
zurueck und versuchst einen neuen Datensatz anzulegen, naja
den Rest weisst du selber!

Ja. Das Problem scheint noch nicht gelöst, aber umgangen. Ich habe ein Refresh eingebaut, nun lauft das Programm durch und die Daten stehen in der Datenbank.

Suchkriterium = Alexander

…LIKE ‚Alexander‘ ->Sucht nach der Zeichenfolge Alexander
…=‚Alexander‘ ->Sucht nach der Zeichenfolge ‚Alexander‘
…=Alexander -> Sucht nach der Zeichenfolge Alexander

Dann mal was anderes. In deiner Function Suche wo du dann true
oder false zuweisst, warum machst dasso umstaendlich?

Weil ich es nicht besser weiß. :smile:

suche=cbool(rs.Recordcount>0)

??? Das muss ich morgen mal ausprobieren, das habe ich noch nie gesehen.

Danke!

Gruß, Rainer

Danke, erledigt …
Hallo Dirk,

danke, erledigt. :smile: Das Programm läuft jetzt seit zwei Tagen ohne Fehler durch. Nun kann ich auch mal wieder eine Tag frei nehmen …

Gruß, Rainer

Hallo Rainer,

hatte den thread mitgelesen.

Erstmal schön für dich, Problem (scheint) gelöst.

Was ich so im Nachgang überlegt habe: Liest du immer aus der DB? Oder wird eine Tabelle gelesen, geändert und nur die Existenz gegen die DB geprüft? Nach dem Motto: Änderungen sind noch im Client (die neuen Zeilen), aber geprüft wird im Server? Würde genau den Effekt haben, und das Refresh() würde den Fehler beheben, da es die Datensätze schreiben dürfte (könnte, sollte???)

mfg

Dirk.Pegasus

Hallo Dirk,

Was ich so im Nachgang überlegt habe: Liest du immer aus der
DB? Oder wird eine Tabelle gelesen, geändert und nur die
Existenz gegen die DB geprüft?

Ich hole aus der Informix-Datenbank immer alle Datensätze, weil ich dort keine Kontrolle habe, was schon an die MDB übergeben wurde. Der Datenfluss ist eine Einbahnstrasse. Änderungen an den Datensätzen gibt es nicht, es kommen nur neue hinzu.

Gruß, Rainer