Neuigkeiten:

Wenn ihr euch für eine gute Antwort bedanken möchtet, im entsprechenden Posting einfach den Knopf "sag Danke" drücken!

Mobiles Hauptmenü

Datensatzaktualisierung auf SQL Server

Begonnen von redithebat, Februar 28, 2019, 12:25:03

⏪ vorheriges - nächstes ⏩

redithebat

 Hallo Zusammen

Nach längerem Googeln habe ich mich entschieden, meine Frage mal hier zu stellen und hoffe, dass jemand mir hier weiterhelfen kann.

Über Access habe ich ein FrontEnd erstellt, welches mit einer Microsoft SQL Datenbank komuniziert. Die Tabellen der Datenbank habe ich über ODBC im Windows eingebunden und im Access hinzugefügt.

Bei der Bearbeitung vom Datensatz sollen bestimmte Spalten aktualisiert werden. Dieser Vorgang habe ich mit folgendem Code gelöst:

   
With CurrentDb.OpenRecordset("select * from DBBriefe where BriefID = " & Me.lstBriefe.Value, dbOpenDynaset, dbSeeChanges)
    .Edit
    .Fields("Status") = "Nicht OK"
    .Fields("DatumBearbeitet") = Now
    .Fields("LoginBearbeitet") = getUsername
    .Update
End With


"Me.lstBriefe.Value" enthält die ID vom Datensatz. Somit wird dabei nur ein einziger Datensatz gezogen.

Dies lief bis anhin gut. Nun habe ich auf dem Server neue Spalten hinzugefügt und die Tabelle mit dem Tabellenverknüpfungs-Manager aktualisiert. Nun kann ich zwar immer noch neue Datensätze generieren, jedoch erhalte ich bei der oben genannten Aktualisierung den Fehler:

[Laufzeitfehler '3197':

Das Micorsoft Access-Datenbankmodul hat den Vorgang angehalten, da Sie und ein weitere Benutzer gleichzeitig versuchen, dieselben Daten zu ändern.]

Dieser Fehler Tritt bei ".Update" auf. Ich kann zwar mit "DoCmd.RunSQL" noch Änderungen vornehmen, jedoch macht dies die Codierung sehr unübersichtlich.
Wichtig zu erwähnen ist, dass bei der alten Version, in der ich die Tabellen noch nicht aktualisiert habe, der Vorgang problemlos funktioniert.

Hat jemand ggf. schon Erfahrungen mit dieser Problematik gemacht?

Gruss
Ale

datekk

Hi Redithebat,

füge der Tabelle auf dem SQL Server eine Spalte vom Datentyp "Timestamp" hinzu. Nullwerte für diese Spalte nicht zulassen. Dies könnte das Problem lösen.
Weiterhin würde ich empfehlen, die Daten direkt auf dem SQL Server via ADODB zu aktualisieren und nicht via "Umweg" über ODBC.

Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

redithebat

Es hat funktioniert. OMG. Du bist der Beste.
Kannst du mir erklähren wesswegen es sich so verhält?

Und kannst du mir ggf. auch erklähren wesswegen die andere Anbindung vorteilhafter wäre?

Tut mir leid wenn ich so viel frage aber ich möchte gerne verstehen. :-)

gruss
redi

datekk

Die Timestamp Spalte wird erforderlich bei Tabellen, welche Gleitkommazahlen bzw. binäre Daten Speichern. Der Grund liegt in der unterschiedlichen Genauigkeit die Access und SQL Server bei diesen Datentypen verwenden.

Sobald Access die Tabelle via ODBC einliest, gilt der Gültigkeitsbereich von Access und die Daten werden in diesem Moment auch auf dem SQL Server bereits überschrieben. Wird nun noch der Datensatz in Access geändert und der Datensatz an den Server übertragen werden die Spalten miteinander verglichen. Da es aber bereits eine Änderung der SQL Daten gab wird die erneute Änderung nicht angenommen - es kommt zu einem Konflikt.

Die Timestamp Spalte sorgt dafür, dass nun nicht mehr die Daten der Spalten gegenseitig verglichen werden sondern der Vergleich erfolgt lediglich über den binären Wert der Timestamp-Spalte.

Zur anderen Frage:

Ein direkt an den SQL Server gebundener Recordset wird nicht erst über den Umweg über die verknüpfte Tabelle ausgeführt sondern direkt am Server. Ich habe mich bei meiner Access Anwendung dazu entschieden, gar keine Tabellen zu verknüpfen und alle Formulare direkt an ein ADODB Recordset zu knüpfen. Die Performance, gerade bei größeren Datensätzen ist dadurch um einiges gestiegen. Weiterhin wird auch das SQL des SQL Servers genutzt und nicht der Access - SQL sprech, was dazu führt, SQL korrekt zu lernen (z.b. Select Concat(Anrede, ' ', Nachname) As AnredeName anstatt Select Anrede + ' ' + Nachname As AnredeName). Dies hilft dann um den deutlich umfangreicheren Modifikations- und Selektionsumfang des Servers nutzen zu können.
Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

PhilS

Danke für die gute und ausführliche Erklärung.Allerdings...
Zitat von: datekk am Februar 28, 2019, 15:00:05Sobald Access die Tabelle via ODBC einliest, gilt der Gültigkeitsbereich von Access und die Daten werden in diesem Moment auch auf dem SQL Server bereits überschrieben.
Dieser Satz, insbesondere der zweite Teil, ergibt für mich keinen Sinn.

Auf dem SQL-Server wird nichts überschrieben, wenn die Daten von Access gelesen werden.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

datekk

#5
Hi PhilS... Ich bin da in dem Bereich nicht der Experte... Ich habe das gleiche Problem wie der TE gehabt und mich damit befasst und belesen. Die Timestamp Spalte wurde dort so erklärt.

Ich denke, so oder ähnlich ist das gemeint:

Der Access Datentyp Double hat eine Genauigkeit von 15 Stellen. Das Pendant 'Decimal' auf MS SQL Server hat eine Genauigkeit von 38. Sprich, wird eine Zahl mit 38 Stellen vom Server an Access geliefert, wird sie dort auf 15 Stellen zusammengekürzt. Damit wird der Datensatz aber bearbeitet und in diesen Zustand versetzt ohne dass der User hier irgendwas eingegeben hat. Dies hat zur Folge, dass man in Access den Hinweis erhält, dass der Datensatz durch einen anderer Benutzer geändert wurde.

What ever... Die Timestamp Spalte hilft, das Problem zu lösen.
Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

markusxy

Zitat von: datekk am März 11, 2019, 14:43:06
...Der Access Datentyp Double hat eine Genauigkeit von 15 Stellen. Das Pendant 'Decimal' auf MS SQL Server hat eine Genauigkeit von 38....

Das ist nicht richtig.
Der Double in Access ist identisch mit dem im SQL Server.
Die Abweichung ist beim Single gegeben.
Der Decimal ist kein Gleitkommatyp, sondern ein sklarierter Ganzzahlentyp.
Die beiden haben nichts miteinander gemeinsam.

datekk

Wie gesagt, da bin ich dann raus. So genau hab ich das nicht studiert.

Was die Zusammenarbeit mit Access und SQL Server anbelangt möchte ich gern das Buch "'ACCESS UND SQL SERVER - Migration und Erstellung von Mehrbenutzeranwendungen" von Bern Jungbluth und Andé Minhorst empfehlen. Dieses geht auf Seite 69 auf diesen Sachverhalt ein.

LG

Access 2016 mit SQL Server Backend. Bereits umgesetzt: Access mit MS SQL Backend,  ADODB Formularbindung, Streamen von Dateien zum SQL Server und zurück (Filestream), Drag&Drop Dateiupload zum Server, CTI / TAPI Integrierung in Access Anwendung - Nutzung auch über Remote Desktop, selbst aktualisierendes Access Frontend auf entfernten Rechnern (Upgrade). Berichte / Kreuztabellen mit SQL Server Backend, Mail Tagging, Outlook Steuerung über Access und umgekehrt // Grundwissen in .Net Core & Blazor Apps

PhilS

Zitat von: markus888 am März 11, 2019, 15:18:18Der Double in Access ist identisch mit dem im SQL Server.
Im Zuge dieser Aussage solltest du aber auch auf die unterschiedlichen Repräsentationen der Werte in ihrer Textform hinweisen.

Access/VBA:

    Dim doubleMaxValue As Double
    doubleMaxValue = CDbl("1,79769313486231570E+308")
    Debug.Print doubleMaxValue

=> 1,79769313486232E+308
(Die obige Schreibweise mit der CDbl-Stringkonvertierung rührt daher, dass schon der VBA-Editor den Double nicht in seiner vollen Genauigkeit aufnehmen möchte.)

SQL-Server:

declare @doubleMaxValue float(53) = 1.79769313486231570E+308
Select convert(varchar(50), @doubleMaxValue, 2 )

=> 1.797693134862316e+308

Erst ab SQL-Server 2016, den ich hier nicht griffbereit habe, gibt es einen Style=3 für Convert, der eine verlustfreie Textrepräsentation des Double ermöglichen soll.

Die hier exemplarisch dargestellten Abweichungen in der Textrepräsentation der Fließkommawerte führen zu dem, von @datekk im wesentlichen korrekt beschriebenen, Problem mit dem Vergleich dieser Werte, wenn sie in SQL-Statements (=Text!) zwischen Access und SQL-Server übermittelt und verglichen werden.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

markusxy

@PhilS,
bis jetzt war ja keine Rede davon, dass der SQL Server bei der Textkonvertierung genauer ist,
sondern dass die Daten unterschiedlich genau gespeichert werden,
was beim Double ja nicht zutrifft, sondern wie erwähnt beim Single.

Das Prinzip ist ja klar, nur die ganze Erklärung bezüglich Double und Decimal ist ja erschrecken daneben.
Auch kein Problem und in der Regel wenig Relevant für die Praxis - nur wissen sollte man es wenn man mit dem Server arbeitet. Deswegen gabs ja auch die Korrektur.
Sollte ich aber mal in die Verlegenheit kommen Double Werte mit dem SQL Server und gleichzeitig mit Access zu Text zu konvertieren und zu vergleichen, werde ich daran denken.
Nur entweder arbeite ich mit Daten aus einem Servers oder mit Daten aus einem Access Backend.
Folglich wäre mir das nie aufgefallen. Also danke für den Hinweis.

Jetzt wäre natürlich noch interessant zu klären, ob die Rundung bei Donkarl - mittels Textkonvertierung ungenau ist.
Es geht zwar eh viel effizienter, ohne die Textkonvertierung - interessant wäre es doch allemal.

Maltes

Hallo, ich habe ds gleiche Problem wie der Thread starter. Ich habe in meiner SQL Datenbank eine Spalte mit Timestamp hinzugefügt. Allerdings habe ich jetzt das Problem das ich gar keine Datensätze mehr ändern kann. Liegt das daran das die Timestamp spalte bei allen Datensätzen leer ist?

PhilS

Zitat von: Maltes am Mai 11, 2020, 13:16:24
Ich habe in meiner SQL Datenbank eine Spalte mit Timestamp hinzugefügt. Allerdings habe ich jetzt das Problem das ich gar keine Datensätze mehr ändern kann. Liegt das daran das die Timestamp spalte bei allen Datensätzen leer ist?
Einte Timestamp-Spalte kann nicht "leer" sein. Sie wird immer mit den jeweils für den Datensatz aktuellen Wert gefüllt.

Hast du die Tabelle(n) nach Hinzufügen des Timestamp neu verknüpft?
Wie genau äußert sich das nicht mehr ändern können? Fehlermeldung? Schreibgeschützt?


Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor