pcfjkg
Goto Top

RowVersion SQL 2008 R2. Update und Delete mittels MS-ACCESS 2010 bringen Fehler oder Warnmeldung.

In eine Tabelle auf dem SQL-SERVER sollen Werte einer weiteren Tabelle geschrieben werden, dazu werden Insert, Delete und Update genutzt. Diese Anweisungen werden durch eine gespeicherte Prozedur auf dem SERVER gegeben, die GP über ein MS-ACCESS Projekt 2010 ausgelöst. Die offensichtlich durch Rowversion und Primary Key ausgelösten Warnmeldungen erscheinen auf der MS-ACCESS - Oberfläche und sind unerwünscht.

Vorab: Ich habe im Netz gestöbert (msdn, blog von olafhelper) und möglicherweise ein grundsätzliches Verständnisproblem zu Transact-SQL und direkt auf dem Server ausgelösten Kommandos (?). Ein MS-ACCESS Unterformular im (*.adp) besaß bisher ungebundene Textfelder. Die dort eingetragenen Werte wurden z.B. mit Docmd.RunSQL (oder ADO.Recordset) in der SERVER-Tabelle verarbeitet. Neuerdings aber habe ich das Unterformular an eine andere Tabelle gebunden. Die muß ja einen Primary Key Identity besitzen, sonst können die Felder nicht editiert werden. Ein Befehlsfeld in ACCESS 2010 startet dann die o.g. GP, in welcher Werte der großen Hauptabelle mit der an das Unterformular gebunden verglichen werden. Dortin der Hauptabelle gibt es keinen Primary Key und kein timestamp bzw. rowversion (Zumindest nicht von mir angelegt). INSERT ist.ok., DELETE und UPDATE funktionieren zwar auch, aber ACCESS meldet diesen Vorgang als lästigen Hinweis jedesmal. Beide Tabellen befinden sich auf dem gleichen SQl-SERVER. Will ich vor diesen UPDATES in der kleineren, an das UF gebundenen Tabelle die rowversion ändern/anpassen - wie in den Beispielen im Netz dargestellt -, so meldet der SERVER bereits beim Speicherversuch der GP im SERVER-Management-Studio Fehler (z.B. das in timestamp-Spalten nichts verändert werden darf o.ä.). Schön wäre ein kurzes Beispiel aber auch ggf. ein Hinweis, wo denn mein Denkfehler liegt, denn es funktioniert ja offenbar bei Anderen (bei mir wird z.B. auch das GO in einer GP im SERVER-Management-Studio nicht akzeptiert,in vielen Beiträgen findet man dies aber, wird teilweise sogar empfohlen).
Danke an alle, die sich hierfür Zeit nehmen.

PCFJKG

Content-Key: 171433

Url: https://administrator.de/contentid/171433

Printed on: April 20, 2024 at 05:04 o'clock

Member: NetWolf
NetWolf Aug 20, 2011 at 18:56:24 (UTC)
Goto Top
Moin Moin,

in den Grundeinstellungen von Access kannst du die Meldungen ein- und ausschalten.
Klar, dass an Timestamp-Feldern keine Änderung zugelassen werden.

Grüße aus Rostock
Wolfgang
(Netwolf)
Member: PCFJKG
PCFJKG Aug 21, 2011 at 20:54:52 (UTC)
Goto Top
Hallo Netwolf, das wär ja einmal eine schöne einfache Lösung (fast zu schön um wahr zu sein), denn ich finde im MS-Access 2010 einen solche Möglichkeit zur Einstellungsänderung nicht. Vielleicht habe ich sie aber nur übersehen oder Du hast einen Hinweise wo ich die Einstellung bei den Optionen finde (bei Client nichts gesehen, Bestätigung bei Änderung/Löschen ist das Kästchen nicht angehakt).

Falls nicht, hast Du trotzdem eine Idee warum der Scrip unten nicht mit dem SQL-SERVER-Management-Studio angelegt werden kann und Fehler bringt (ansonsten könnte ich ja dort weiterbasteln aber wie gesagt, bereits das <GO> wird nicht akzeptiert ...
Zitat von OlafHelper:
Im MS SQL Server ist das mit einem einfachen Kniff leicht möglich, ohne eine Programmanpassung vornehmen zu müssen. Für Update legt man ein Feld mit Typ Timestamp an, für Insert ein Feld vom Typ Binary(8), bei dem das Default auf @@DBTS +1 gesetzt wird. Natürlich weist man dem Feld nie ein Wert zu, sondern belässt man den Default; also dem Timestamp zu Zeitpunkt des Inserts.

Sieht dann so aus:


USE tempdb
--TempDB um mit @@DBTS die richtigen Werte zu bekommen
GO
CREATE TABLE #TS
(Id int identity(1,1),
UpdateTS timestamp,
InsertTS binary(6) DEFAULT @@DBTS + 1);

-- 3 Datensätze zur Demo
INSERT INTO #TS DEFAULT VALUES;
INSERT INTO #TS DEFAULT VALUES;
INSERT INTO #TS DEFAULT VALUES;
-- Einen davon Updaten
UPDATE #TS
SET InsertTS = InsertTS
WHERE Id = 3
-- Wie sieht es aus?
SELECT * FROM #TS;
-- ... gut
GO
DROP TABLE #TS
Ende Zitat von OlafHelper.

Auch hier schon einmal Dank für jede Idee.
PCFJKG
Member: NetWolf
NetWolf Aug 24, 2011 at 18:37:17 (UTC)
Goto Top
Moin Moin,

Bestätigung bei Änderung/Löschen ist das Kästchen nicht angehakt).
diese Einstellung war gemeint, damit werden die lästigen Meldungen normaler Weise abgeschaltet.

Falls nicht, hast Du trotzdem eine Idee warum der Scrip unten nicht mit dem SQL-SERVER-Management-Studio angelegt werden kann und Fehler bringt
da muss ich noch forschen ....

Grüße aus Rostock
Wolfgang
(Netwolf)
Member: PCFJKG
PCFJKG Aug 25, 2011 at 06:11:00 (UTC)
Goto Top
Danke, dass Du Dir die Mühe machen willst.


Viele Grüße

PCFJKG
Member: NetWolf
NetWolf Aug 25, 2011 at 19:46:48 (UTC)
Goto Top
so pauschal erstmal so zum testen:

USE tempdb; <- mit Semikolon abschließen
GO

Gruß
Netwolf
Member: PCFJKG
PCFJKG Aug 26, 2011 at 00:20:27 (UTC)
Goto Top
Hallo Netwolf,
Du bist ja echt fleißig.
Leider Meldung:

USE database-Anweisung ist in Prozedur, Funktion oder Trigger nicht zulässig.

Viele Grüße
PCFJKG
Member: Biber
Biber Aug 26, 2011 at 08:43:45 (UTC)
Goto Top
Moin PCFJKG,

lass bitte mal das USE tempdb weg - eine USE database-Anweisung wird in StPs oder Triggern immer intern implizit gesetzt (und lässt sich im Umkehrschluss nicht explizit angeben).

Qualifiziere stattdessen die Tabellen/Datenbankobjektangaben voll z.B.

 CREATE [dbo].[tempdb].#TS

Dann wird ja auch - wie es dein Plan ist- TempDB angefasst, "um mit @@DBTS die richtigen Werte zu bekommen".

Grüße
Biber
Member: PCFJKG
PCFJKG Sep 06, 2011 at 09:58:31 (UTC)
Goto Top
Hallo Biber,

sorry dass ich jetzt erst anworte, ich habe ein neues Notebook und die Mail-Portierung hatte ein Problem...
Zur Sache selbst: Ich denke jetzt sind wir wieder auf der richtigen Spur, soll heißen ich werde mich @@DBTS widmen ..
Mal sehen, ob sich der Wert der Rowversionsspalte ändern lässgt. Ggf. würde ich Deine Hilfe gern noch einmal in Anspruch nehmen, noch besser, ich würde gern Erfolg! melden.

Viele Grüße

PCFJKG
Member: PCFJKG
PCFJKG Sep 07, 2011 at 00:44:46 (UTC)
Goto Top
Hallo Biber,

sorry, aber noch einmal grundsätzlich zu Rowversion. Ich dachte bisher, man kann die UPDATE-Meldung umgehen, indem man in die Rowversion-Spalte den aktuellen Wert von @@DBTS schreibt (oder einen anderen, den das Sytem nicht kennt und somit keinen Vergleich mit irgendwelchen internen Werten durchführen kann) . Dann "denkt" der SQL-SERVER es wäre so von Anfang an gewesen, also o.k. und kein UPDATE welches es zu melden gibt.
Aber es ist vermutlich ganz anders und mit einem geänderten Eintrag in die Rowversion erreiche ich mein Ziel ohnehin nicht, denn bereits die Anweisung in der Gespeicherten Prozedur:

UPDATE ##T_Rkva06 set RV = 0x00000000000007D3
bewirkt die Meldung:

Eine timestamp-Spalte kann nicht aktualisiert werden.

Den Wert 0x00000000000007D3 für die RV-Spalte habe ich (als Test) als einen möglichen im Internet gefunden.

Am liebsten würde ich das alles verstehen, aber wenn es ein Beispiel gibt welches die Meldung UPDATE bzw. DELETE unterdrückt ohne die RowVersion-Angelegenheit zu begreifen, wäre mir auch geholfen, auch wenn ich damit nicht so recht glücklich bin... Letztendlich muss ich abere in erster Linie weiterkommen und manchmal kommt ja der AHA-Effekt durch learning by doing ohnehin schneller (o.k., manchmal auch nicht).

Solltest Du für ein Beispiel in einer Gespeicherten Prozedur Zeit haben, bin ich sehr dankbar, aber natürlich auch für jeden anderen Denkanstoß.

Viele Grüße

PCFJKG
Member: Biber
Biber Sep 07, 2011 at 08:28:33 (UTC)
Goto Top
Moin PCFJKG,

ich bin jetzt ein bisschen am Schwimmen, was deinen Plan angeht.

nochmal grundsätzlich...
Die Fehlermeldung 272 ("Spalte vom Typ timestamp ist nicht updatable") ist natürlich gerechtfertigt, denn der Typ "Timestamp" hat nix,nix, nix mit den SQL-Datentypen Datum oder Zeit zu tun, sondern steht als Synonym für "Rowversion".
Also genau diese Binary-Repräsentation, die du auch in Weiten des Netzes ausgraben hast.
Dat Dingen kann der SQL-Server handeln, du aber nicht (per UPDATE-Statement).

ich frag mal anders - was würdest du denn (von der Programmlogik her) aus einem geänderten Wert in der Timestamp-Spalte ableiten wollen?

Grüße
Biber
Member: PCFJKG
PCFJKG Sep 07, 2011 at 13:39:51 (UTC)
Goto Top
zunächst danke für die schnelle Antwort. Meine Erklärung vielleicht so:
Ich bin etwas vernarrt in GP'n, sie sind schnell in der Ausführung und man kann mit ihnen fast jede Aufgabe professionell lösen. Ich erstelle diese prinzipiell im MS-SERVER-Management-Studio. Unter anderem deshalb habe ich verschiedene UPDATE-Anweisungenin einer GP, die eben schnell (und absolut korrekt) die Feldwerte in Zeilen einer ##-Tabelle berechnen. Z.B.:
SET @cmdstr = 'UPDATE ##-Tabelle SET MwSt = (''1.''+ CAST(MwStKz AS NVARCHAR(2))) * Netto – Netto WHERE '+@Bedingung
EXEC(@CmdStr)
Zuvor wurde aber z.B. der Wert für Netto in dieser ##-Tabelle einer MS-ACCESS 2010 *.adp durch eine Eingabe im Textfeld eines Unterformulares Upgedatet, oder auch in einem anderen Textfeld die in die einerin Spalte gespeicherte Anzahl o.ä. z.B. mit
DoCmd.RunSQL "UPDATE ##-Tabelle & " SET ANZ = " & Me.TF_Anz & " WHERE ZNr = " & Me.TF_ZNr
Anschließend rufe ich ohne Probleme die o.g. GP auf, welche auch problemlos die gewünschten UPDATES ausführt.
Sobald ich nun das Haupformular schließe (und damit das betreffende Unterformular, die dortige RecordSource ist diese ##-Tabelle mit einem PRIMARY-KEY), kommt halt die MS-ACCESS Meldung, Schreibkonflikt. Dieser Datensatz wurde seit Beginn der Bearbeitung vom einem anderen Benutzer usw. usf.
Nun hatte ich die Idee, wenn ich in der ##-Tabelle eine Spalte Rowversion einfüge und der Wert der Rowversion mittels der GP so ersetzt wird, dass die Situation beim Schließen des Formulars von MS-ACCESS nicht als UPDATE (oder DELETE, wenn Zeilen gelöscht wurden) bewertet bzw. interpretiert wird, dann die o.g. Fehlermeldung/ Information nicht mehr erscheint.
GGf. ist das mit der rechten Hand über den Kopf am linken Ohr gekratzt, aber bei der Gelegenheit hatte ich gehofft, die ab MS-SQL-W2k8-SERVER neu eingeführte Rowversion zu verstehen und zu nutzen. Vielleicht hängen aber hier die Trauben etwas zu hoch und ich muß meine Aufgabenstellung irgendwie anders lösen, mal sehen.
Ich hoffe, mehr zur Entwirrung als zur weiteren Verwirrung meines Problems beigetragen zu haben und deshalb in jeden Fall, danke für Deine Geduld.

Viele Grüße
PCFJKG
Member: Biber
Biber Sep 07, 2011 at 15:10:28 (UTC)
Goto Top
Moin PCFJKG,

ich bin eher skeptisch, ob du da an der richtigen Stelle gräbst.

Wenn denn am Ende des Tages bzw. beim Schliessen des Hauptforulars gemeckert wird, dass dieser Satz geändert wurde (seit dem letzten Lesen)...
-> dann würde ich behaupten, dieser Hauptformular-Datensatz ist nach den UPDATEs meinetwegen durch eine StP nicht refresht/neu gelesen worden.

Eventuell hast du dir dadurch ein Bein gestellt, dass du Änderungen sowohl direkt im Hauptformular zulässt und ebenso Änderungen desselben Satzes über Bande/über Unterformular.

Wäre denn dann nicht eine geschicktere Strategie, wenn bei jedem Wechseln (=focus on) von Haupt- auf Unterformular et vice versa ein Refresh des Hauptformulardatensatzes angeschubst wird?

Grüße
Biber
Member: PCFJKG
PCFJKG Sep 08, 2011 at 02:30:05 (UTC)
Goto Top
Hallo Biber,

ich glaube inzwischen auch, dass ich hier das Konzept neu überdenken muss, wobei ich Deinen Hinweis mit dem Refresh probiert habe, momentan leider ohne Erfolg (ich hatte auch nicht erwähnt, dass das Hauptformular keine RecordSource besitzt, in die dortigen Textfelder werden diverse Werte mit dlookup() eingelesen).
Ein me.refresh (oder auch me.parent.refresh) bewirkt ebenso sofort die betreffende MS-Access Meldung.

Nun wollte ich mit dem PK etwas versuchen (z.B. diesen löschen und nach dem update neu anlegen oder etwas in der Art und Weise), stolpere momentan über die ALTER – Anweisung und hoffe Du kannst auch dabei helfen. Vermutlich liegt der Fehler beim DROP des CONSTRAINT-Namens, denn auch wenn ich den Systemname von sys.key_constraints auslese und verwende, wird PK nicht gelöscht:

ALTER TABLE dbo.##-Tabelle ADD PK tinyint CONSTRAINT PKTmp NOT NULL IDENTITY PRIMARY KEY
ALTER TABLE dbo.##-Tabelle DROP CONSTRAINT PKTmp
ALTER TABLE dbo.##-Tabelle DROP Column PK
Nun komme ich also auch hier nicht weiter, manche Tage sind eben wirklich eher geeignet spazieren zu gehen und den PC in die Ecke zu stellen – egal bei welchem Wetter. Aber nach jedem Tief kommt ja bekanntlich ein Hoch (heißt es) …
Erneuten Dank für Deine Hilfe und viele Grüße von

PCFJKG
Member: PCFJKG
PCFJKG Sep 08, 2011 at 13:08:39 (UTC)
Goto Top
Sorry Biber,

es muss natürlich als ALTER TABLE ##-Tabelle ADD PK tinyint NOT NULL IDENTITY CONSTRAINT PKTmp PRIMARY KEY angewiesen werden.
Hoffentlich hast Du noch keine Zeit in dieser Sache vertan, ich war vermutlich irgendwann in dem berühmten Wald, den man vor lauter Bäumen nicht sieht.

Gern würde ich in der Rowversionssache bzw. einem ggf. "neuen" Weg noch einmal auf Deine Kenntnisse zurückkommen, soweit Du einverstanden bist, denn jetzt kann ich erst einmal weiter trial and error nutzen.

Vielen Dank


PCFJKG