Logik im Netzwerk

Alles zum SQL-Dialekt

Moderator: Moderatoren

Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Logik im Netzwerk

Beitrag von Werner_Bayern »

Servus,

da ich gerade von dbf auf PostgreSQL umstelle (direkt, bzw. Universal-SQL, nicht ISAM), hier eine grundsätzliche Frage:

Wie macht man das am besten in SQL mit dem rlock? Beispiel: Artikel-DBF, neuer DS:

DBF:
1. Benutzer erfasst neue Artikelnr.
2. Prüfung, ob die nicht schon vergeben ist
3. Wenn ok, DS wird erzeugt, Artikelnr. (PRIMARY KEY) wird gespeichert
4. Satz wird gesperrt (durch das dbAppend() von 3.)
5. Restliche Daten werden durch Benutzer erfasst
6. Rest wird geschrieben, oder leerer DS wieder gelöscht
7. unlock

in SQL (umgangssprachlich):
2. select artnr from Artikel where artnr = nNeueNr
3. wenn leeres Resultset, dann insert
4. Prüfung, ob insert erfolgreich???
5. Wie verhindere ich, dass diesen leeren Satz keiner bearbeitet? Neue Spalten mit gesperrt, gesperrt durch, gesperrt Uhrzeit? Anpassung select-Anfrage von 2.?

Wie macht ihr das?

Ebenso beim Ändern eines DS? Erst der select, dann vor dem update nochmal ein select, ob sich was geändert hat? Und dann?
es grüßt

Werner

<when the music is over, turn off the lights!>
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Logik im Netzwerk

Beitrag von georg »

Guten Morgen, Werner -


also, vom reinen SQL-Standpunkt aus gibt es kein APPEND BLANK, sondern ein INSERT INTO table VALUES(....). Alternativ kann man auch nur einige Felder beschicken: INSERT INTO table (field, field, ...) VALUES(...)

Da wir mit der SQL-Datenbank über ein API kommunizieren (also einen Aufruf einer C-Funktion), erhalten wir ein Ergebnis zurück. In Zusammenspiel mit MySQL lautet die Frage dann:

Code: Alles auswählen

nResult := oCursor:realQuery(cSelec)
IF nResult <> MYSQL_OK
Das Update ist etwas tricky, weil die üblichen Sperrmechanismen in SQL nicht vorhanden sind. Ich habe ein TIMESTAMP-Feld in jedem Datensatz drin. Ein solches Feld wird bei MySQL IMMER aktualisiert, wenn der Datensatz geändert (bzw. geschrieben) wird, auch dann, wenn es nicht explizit in der UPDATE (oder INSERT) Anweisung angesprochen wird.

Jetzt unterstützt MySQL ein "SELECT ... IN SHARED MODE" und auch ein "SELECT ... FOR UPDATE", damit wird der Datensatz gesperrt. Wenn das TIMESTAMP-Feld einen unveränderten Wert enthält, kannst Du dann das UPDATE durchführen. Ansonsten musst Du den Anwender informieren, dass ein anderer bereits eine Änderung durchgeführt hat.

Jetzt ist sicherlich bekannt, dass ich mich nicht mit der SQL-Verhunzung rumschlage, die Alaska bereitstellt, sondern mit dem MySQL-API arbeite, das Hector Peroza entwickelt hat. Zumindest in den ersten Betas war erkennbar, dass Alaska den Tabellen weitere Felder hinzugefügt hat, um ein xBase-typisches Verhalten simulieren zu können. Damit wird aber SQL aus meiner Sicht extrem ausgebremst.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Logik im Netzwerk

Beitrag von Herbert »

Georg, das trifft nur begrenzt zu. Was SQL eben nicht kann, ist dem ausgehenden System (hier Xbase) mitteilen, wann ein Record gesperrt ist, also muss das aufrufende System dies kontrollieren. Steffen hat das damals anlässlich einer Tagung sehr gut erklärt. So wie ich das verstanden habe macht ein Zusatzfile die Synchronisation zwischen den beiden Systemen, welches wie du korrekt schreibst mit ein paar Feldern in der Tabelle spricht. SQL selber merkt davon meiner Meinung nach eher wenig.
Es geht schliesslich um die Code-Kompatibilität.
Grüsse Herbert
Immer in Bewegung...
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Logik im Netzwerk

Beitrag von georg »

Hallo, Herbert -


das ist die Entscheidung, die zu treffen ist: die Code-Logik von dBase beibehalten, oder im vollen Umfang nutzen, was SQL kann.

Es ist ja nicht so, dass SQL was ganz Neues ist, und man vorsichtig auslotet, was geht und was nicht. SQL (in allen seinen Dialekten) ist heute nicht mehr wegzudenken, und es hätte diese Bedeutung nicht erlangt, wenn Sperrmechanismen nicht richtig funktionieren würden und erst Steffen den Weg gefunden hätte, das endlich zu lösen.

Es geht hier auch um den Weg, wie man mit Daten umgeht. Ich sollte vielleicht einmal eine Umfrage starten, wie mit Datensatzsperren umgegangen wird, und ich fürchte, viele sperren den Datensatz für eine Bearbeitung im Dialog, sobald er gelesen wurde und halten die Sperre aufrecht, während der Datensatz "bearbeitet" wird - also im schlimmsten Fall über Stunden hinweg.

Mein Verständnis ist, dass ich den Datensatz nur so lange sperre, wie es absolut erforderlich ist, und keinen Tick länger. Also, der Anwender kann machen was und wie lange er will. Wenn der seine Änderungen abschickt, wird der Datensatz gelesen und gesperrt. Ist der TIMESTAMP unverändert, wird aktualisiert. Andernfalls wird der Datensatz freigegeben und dem Anwender mitgeteilt, dass er einfach etwas schneller arbeiten muss.

Das kann auch bedeuten, dass ich meine Daten anders designen muss, damit sie diesen Anforderungen entsprechen. Um ein Beispiel zu benennen: ich kann den Warenbestand nicht im Stammsatz des Artikels hinterlegen, da eine Änderung von Stammdateninformationen fast unmöglich ist, wenn ein Artikel mit hohem Umschlag bearbeitet wird (ich weiss, es gibt die Möglichkeit, lagerplatz-bezogene Bestände zu führen - genau auf eine solche Unterscheidung will ich hinaus).

Die Information, ob ein Datensatz gesperrt ist oder nicht, steht tatsächlich nicht zur Verfügung. Aber trotzdem kommen SQL-Programmierer ohne diese Information aus. Beispielsweise, weil die Sperre des Satzes nicht funktioniert und als entsprechender Code zurückgemeldet wird - nach einer im Server definierten Wartezeit.

SQL ist und bleibt ein Paradigmenwechsel, der sich auch auf den Code auswirken muss.

Ein Vorteil von SQL ist die plattforumunabhängige Nutzung. Wenn aber eine Tabelle durch die Feldhinzufügungen durch Alaska ein proprietäre Eigendynamik bekommt, wird die Nutzung der Tabelle von dritter Seite (sagen wir mal, im PHP-programmierten Webshop) extrem schwierig, weil die in den zusätzlichen Feldern hinterlegte Logik dokumentiert (!) und verstanden werden muss, ehe die Daten genutzt werden können.

Dem Xbase-Programmierer macht es die Sache leichter, mit seinen altbekannten Befehlen zu arbeiten, aber jeder andere, der die Daten nicht mittels Xbase-Programmen bearbeitet, bekommt einen erheblichen Overhead aufgedrückt.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
nightcrawler
1000 working lines a day
1000 working lines a day
Beiträge: 650
Registriert: Di, 24. Apr 2012 16:33
Wohnort: 72184 Weitingen
Hat sich bedankt: 3 Mal
Danksagung erhalten: 96 Mal
Kontaktdaten:

Re: Logik im Netzwerk

Beitrag von nightcrawler »

Es gab ja schon gute Anregungen in diesem Thread. SQL ist, wie von den meisten geschrieben, eine ganz andere Herangehensweise als ISAM. Um eine Art Sperrmechanismus zu bekommen, implementieren manche DBMS ein "SELECT FOR UPDATE". Meiner Meinung nach ist dies aber nur eine Krücke. Einen Timetamp zu benutzen ist sicherlich schon ein Ansatz, in einer Real-Umgebung aber nicht zu gebrauchen, wenn viele Updates gefeuert werden. Ein besserer Ansatz ist es, eine Art Änderungs-Zähler einzubauen. Falls dieser nicht bereits existiert (beim ADS zum Beispiel mit dem Datentyp ROWVERSION), so solltest Du einen selber einbauen und per Trigger kontrollieren.
Folgendes Beispiel (ADS Code) verdeutlicht beides:

Code: Alles auswählen

create table rowversiontest(id autoinc, t char(20), rver integer, rowver rowversion);

create trigger trig_ins on rowversiontest instead of insert
begin
  update __new set rver=1;
  insert into rowversiontest select * from __new;
end;

create trigger trig_upd on rowversiontest instead of update
begin
  update rowversiontest 
    set rver=rver+1, t=__new.t 
    where id=__new.id;
end;

insert into rowversiontest(t) values('hallo');
select * from rowversiontest;
Die beiden Trigger ersetzen die INSERT- und UPDATE-Operation vollständig. Wenn nun ein Datensatz geändert wird, so schaut man vorher, welche Version und welche ID dieser hat und macht das Update dann auf genau diese Situation:

Code: Alles auswählen

update rowversiontest set t='hallo welt' where (id=1) and (rver=1);
select * from rowversiontest;
Gibts es ein Update (UpdateCount=1), bist Du der Sieger. Bei 0 hatte jemand anderes die Finger dran und bei 2 hast Du mindestens eine Verdopplung der ID (Uneindeutigkeit und damit eh ein Fehlerzustand).

Code: Alles auswählen

update rowversiontest set t='hallo welt' where (id=1) and (rver=1);
if ::stmt.UpdateCount>0 then
  select * from rowversiontest;
else
  select 'fehler' from system.iota;
end;
Falls es bereits einen Datentyp gibt, welcher die Datensatzversion repräsentiert (beim ADS zB rowversion), dann entfallen die Trigger ersatzlos und Du kannst die Updates auf die Bedingung (ID= ...) AND (rowver=...) feuern.
Wichtig bei SQL: Denke mit einer getrennten Datenmenge. Verbinden - Daten holen - Trennen. Verbinden - Daten ändern - Trennen.
--
Joachim
Joachim Dürr Softwareengineering
https://www.jd-engineering.de
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Logik im Netzwerk

Beitrag von Tom »

Hallo, Werner.

Ergänzend zu den bisher vorhandenen Anmerkungen stelle ich mir beim Lesen Deines Postings vor allem (und zwar für jeden Datenbankkontext) die Frage, wo die Artikelnummer herkommt. Es gibt mindestens zwei denkbare Szenarien:

1. Sie wird vom System generiert. Dann wäre eine manuelle Erfassung obsolet; die Artikelnummer wäre quasi eine Antwort der Datensatzerzeugung. Als zugrundeliegender Mechanismus wäre vom Auto-Increment über Trigger, Stored Procedures oder simple Verwaltungstabellen alles denkbar, ggf. sogar ein Abgleich mit Fremdsystemen

2. Sie ergibt sich aus den zu erfassenden Daten, liegt also als Teil der zu erfassenden Daten vor. In diesem Fall stellt sich die Frage, warum mehr als eine Person gleichzeitig diesen Artikel anlegen sollte(n). Um diesen Fall abzudecken, bietet sich in aller Regel eine zweistufige Erfassung an: Zunächst wird nur die Artikelnummer abgefragt, und die Folgedaten dürfen erst dann erfasst werden, wenn der Artikel nicht im Bestand ist, ansonsten würde es sich um eine Stammdatenänderung handeln. Die dann wiederum einen neuen Prozess auslösen müssten - versehen mit entsprechenden Mechanismen, die einer Doppelbearbeitung vorbeugen. Auch hierbei wäre letztlich unerheblich, ob SQL oder ISAM verwendet werden. Viele bilden an dieser Stelle simple Last-in-first-out-Strukturen ab

Dies nur am Rande, quasi geschäftslogisch und, wie erwähnt, unabhängig vom Datenbankkontext.
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Logik im Netzwerk

Beitrag von AUGE_OHR »

Werner_Bayern hat geschrieben:Wie macht man das am besten in SQL mit dem rlock? Beispiel: Artikel-DBF, neuer DS:
du "denkst" immer noch in xBase (alle Versionen) ...

mit einem SELECT löst du eine Transaktion aus.
eine Transaktion starte mit BEGIN und endet mit COMMIT
eine Transaktion ist erst dann sichtbar wenn sie abgeschlossen wurde.
jede Transaktion ist nur ein "Schnappschuss" der Daten und kann sich inzwischen geändert haben

Transaktionen werden in der Reihenfolge des Eingang abgearbeitet.
ein "gleichzeitiger" Zugriff ist deshalb nicht möglich und keine "extra" Sperre notwendig.

wenn 2 Stationen den selben Record editieren dann gibt es nur die "letzte" Version.

angenommen, unter xBase, ich "sperre" eine Auftragsnummer zwecks Bearbeitung damit "andere" nicht gleichzeitig was ändern.
Frage : was wenn jemand anders 1 Std. später, weil "unwissend", nochmals den selben Auftrag/Position verändert ( 10 Kt xy mehr ... )

das ist nun tatsächlich eher der Fall als dass 2 Personen "in der selben Sekunde" einen Datensatz bearbeiten/sperren wollen.
---

wenn du nun in ISAM "denkst" dann überlege mal was Alaska sich bei den "internen" Feldern gedacht hat welche beim "Upgrade" DBF -> PostgreSQL eingefügt werden.

cQuery += " __deleted boolean NOT NULL DEFAULT false, "
cQuery += " __record serial NOT NULL, "
cQuery += " __rowversion integer NOT NULL DEFAULT 0, "
cQuery += " __keyversion integer NOT NULL DEFAULT 0, "
cQuery += " __lock_owner integer NOT NULL DEFAULT 0, "

---

in den Stamm-Datein gibt es selten das Problem im Multi User Betrieb weil meistens nur "lesen" benötigt wird.
anders bei Bewegungs-Daten z.b. Auftragserfassung die täglich anfallen auf die ich mich im weiteren beziehe.

bei mir gibt es die Felder Datum, Uhrzeit, User.
vor dem editieren hole ich mir die Info.
vor dem "save" frage ich es noch mal ab (im Thread) ob sich an Datum/Uhrzeit was geändert hat.
wenn alles OK kommt ein Doppelschritt : "lösche" alten Satz, füge neuen hinzu.

das intern Feld "__deleted" ist dabei nützlich während "__record" ( Type serial ) ein Problem machen könnte bei einem "PACK".
am Ende des Tages kopiere ich alle "gelöschten" Datensätze in eine Temporäre DBF/Tabelle und hänge die an das Logbuch an.

bei einer DBF kann ich, nach dem "PACK", den Index neu aufbauen.
bei der SQL Table würde durch das löschen "Löcher" in der Reihenfolge von "__record" auftreten ... im Prinzip egal solange nicht doppelt (serial) !

wenn man es trotzdem "ohne Löcher" haben will :
1.) Table umbenennen
2.) neue Table anlegen
3.) importieren der Daten aus der alten Table ohne das Feld "__record" ( was selbständig rauf zählt )
gruss by OHR
Jimmy
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Logik im Netzwerk

Beitrag von Werner_Bayern »

georg hat geschrieben:

Code: Alles auswählen

nResult := oCursor:realQuery(cSelec)
IF nResult <> MYSQL_OK
Servus Georg,

danke. Das mit insert war mir schon klar, hatte ich ja schon geschrieben. Der von Dir gezeigte Code geht m. W. n. mit PostgreSQL nicht, da muss man es so machen:

Code: Alles auswählen

oStmt := DacSqlStatement(soSession):FromChar(cBefehl)  // z. B. "select artnr from Artikel order by artnr Limit 1000" 
oStmt:Build():Query(nResultType, @xVar)
Wobei hier noch mehrere Fehler seitens Alaska sind, z. B. bekommt man immer ein Resultset in Form einer Workarea zurück, egal was man der Query()-Methode übergibt.

Was hier auch nicht schön ist: Übergibt man einen ungültigen Befehl, oder z. B. den Primary Key doppelt, geht's in die Errorsys (auch hier ein Fehler, weil Meldungen im falschen Zeichensatz kommen). Man muss also vor jedem SQL-Befehl einen eigenen Errorhandler installieren, weil es sonst unschöne Abbrüche gibt.
Das scheint in MySQL mit der entsprechenden Klasse schöner gelöst zu sein...

TIMESTAMP gibt es in PostgreSQL auch. Da muss also nichts extra gemacht werden, einfach nur so ein Feld anlegen?

Shared Mode und for update scheint PostgreSQL nicht zu unterstützen.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Logik im Netzwerk

Beitrag von AUGE_OHR »

Werner_Bayern hat geschrieben: Shared Mode und for update scheint PostgreSQL nicht zu unterstützen.
schon mal unter "13.3.2. Row-level Locks" geguckt ?
Werner_Bayern hat geschrieben:Das scheint in MySQL mit der entsprechenden Klasse schöner gelöst zu sein...
dann frage ich mich warum du nicht die "native" PostgreSQL Class nimmst :-"
beide Class(en) von Hector "könnte" man auch zu einer zusammenfassen was z.b. die Navigation in einem Resultset angeht.
gruss by OHR
Jimmy
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Logik im Netzwerk

Beitrag von georg »

Hallo, Werner -


ich bin von Hector's Implementierung so begeistert, dass ich gar nicht mehr über die SQL-Implementierung (höh, höh) von Alaska nachdenke.

Da ich vor Jahren schon die ganzen DBF-Zugriffe über eine Klasse gekapselt hatte, war die Umstellung kein so grosser Aufwand mehr.

Was TIMESTAMP in PostgreSQL angeht: einfach eine kleine Tabelle anlegen, einen Satz einfügen, anzeigen, ein Feld ändern, Satz erneut anzeigen, das TIMESTAMP-Feld sollte jetzt einen anderen Wert haben.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Logik im Netzwerk

Beitrag von Werner_Bayern »

AUGE_OHR hat geschrieben:dann frage ich mich warum du nicht die "native" PostgreSQL Class nimmst :-"
Was ist das, was meinst Du damit? Wo finde ich die?
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Logik im Netzwerk

Beitrag von Werner_Bayern »

georg hat geschrieben:Mein Verständnis ist, dass ich den Datensatz nur so lange sperre, wie es absolut erforderlich ist, und keinen Tick länger. Also, der Anwender kann machen was und wie lange er will. Wenn der seine Änderungen abschickt, wird der Datensatz gelesen und gesperrt. Ist der TIMESTAMP unverändert, wird aktualisiert. Andernfalls wird der Datensatz freigegeben und dem Anwender mitgeteilt, dass er einfach etwas schneller arbeiten muss.

Beispielsweise, weil die Sperre des Satzes nicht funktioniert und als entsprechender Code zurückgemeldet wird - nach einer im Server definierten Wartezeit.
Das ist ja genau der Punkt, unabhängig von SQL: Ansichtssache. Ich vertrete den Standpunkt, lieber gleich dem Anwender zu sagen, er kann diesen einen Datensatz jetzt nicht bearbeiten, weil den zufällig gerade jemand anderes bearbeitet. Mach was anderes (oder schick dem eine Nachricht etc.).
Stell Dir vor, man macht das nicht so, der Anwender erfasst (z. B. Memofeld) umfangreiche Daten, schreibt z. B. ein Gesprächsprotokoll, und dann kommt die Meldung: "Daten werden nicht gespeichert, schreib gefälligst schneller"?

Was meinst Du mit Deinem letzten Satz?

Danke!
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Logik im Netzwerk

Beitrag von Werner_Bayern »

Servus Joachim,

ganz verstehe ich das nicht, aber wo ist der Unterscheid zum Timestamp? Und was sagst Du zum Thema umfangreiche Datenerfassung und dann wird das update verweigert, weil jemand anderes zwischenzeitlich auch was gemacht hat?
nightcrawler hat geschrieben:Wichtig bei SQL: Denke mit einer getrennten Datenmenge. Verbinden - Daten holen - Trennen. Verbinden - Daten ändern - Trennen.
Ist mir inzwischen klar geworden. Geht ja bei DBF auch.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Logik im Netzwerk

Beitrag von Werner_Bayern »

Tom hat geschrieben:wo die Artikelnummer herkommt
Servus Tom,

hatte ich geschrieben, wir machen das bisher so: Die nächste höhere Artikelnr. wird vorgeschlagen, der Benutzer kann diese jedoch frei vergeben. Es wird anschließend geprüft, ob die noch nicht vergeben ist, nur dann erfolgt das insert / append blank, ansonsten nicht. Ich hab die schon als Primary Key definiert.
Tom hat geschrieben:In diesem Fall stellt sich die Frage, warum mehr als eine Person gleichzeitig diesen Artikel anlegen sollte(n).
Das soll ja ausgeschlossen werden. Da hilft mich auch kein Autoinkrement, da ich es dem Benutzer überlassen will, selber eine freie Nummer einzugeben. Bisher wird diese dann geprüft, ist sie neu, wird ein neuer Satz angelegt und gespeichert, damit der nächste diese Nummer nicht nochmal vergeben kann oder bekommt.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Logik im Netzwerk

Beitrag von AUGE_OHR »

Werner_Bayern hat geschrieben:
AUGE_OHR hat geschrieben:dann frage ich mich warum du nicht die "native" PostgreSQL Class nimmst :-"
Was ist das, was meinst Du damit? Wo finde ich die?
da wo du auch das native MySQL her hast : bei Pablo :-)

das original war ja von Phil Ide ( 02.04.2004 )
XbPgSql
xfree.idep.resources
17. November 2008
was mit BAP arbeitet

von Pablo gibt es die Version mit ot4xb statt BAP welche auch Hector in dieser Version benutzt
Postgresql on Xbase++
xfree.resources
14. September 2012
bei Pablo gibt es auch mein PostgreSQL Tool
PGu.EXE
xfree.public
26. Juli 2012
gruss by OHR
Jimmy
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Logik im Netzwerk

Beitrag von georg »

Guten Morgen -


http://dev.mysql.com/doc/refman/5.7/en/datetime.html

Wird bei MySQL ein TIMESTAMP-Feld als TIMESTAMP(6) definiert, geht die Erfassung in die Mikrosekunden rein:

Code: Alles auswählen

+----------------------------+
| arttimestamp               |
+----------------------------+
| 2016-01-08 10:21:01.938302 |
M.E. genügt das für eine klare Differenzierung bei der Dialogverarbeitung.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
nightcrawler
1000 working lines a day
1000 working lines a day
Beiträge: 650
Registriert: Di, 24. Apr 2012 16:33
Wohnort: 72184 Weitingen
Hat sich bedankt: 3 Mal
Danksagung erhalten: 96 Mal
Kontaktdaten:

Re: Logik im Netzwerk

Beitrag von nightcrawler »

Werner_Bayern hat geschrieben:ganz verstehe ich das nicht, aber wo ist der Unterscheid zum Timestamp?
Timestamp ist nicht eindeutig, d.h. ein anderer Benutzer könnte genau zum selben Zeitpunkt ändern.
Und was sagst Du zum Thema umfangreiche Datenerfassung und dann wird das update verweigert, weil jemand anderes zwischenzeitlich auch was gemacht hat?
der beste Weg: die breiten Tabellen noch weiter zu zerlegen, so dass nur noch einzelne Entitäten drin stehen und nicht mehr Adresse1, Adresse2, Adresse3....
--
Joachim
Joachim Dürr Softwareengineering
https://www.jd-engineering.de
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: Logik im Netzwerk

Beitrag von Rudolf »

Hallo,
ich verwende einen Timestamp, den User welcher sperrt und die Art der Bearbeitung. Damit wissen andere wer was wann ändert. In den Dialogen habe ich einen Timeout, User kann also beruhigt auf Mittag gehen ohne dass Satz gesperrt bleibt. Bei Anstürzen bleibt der Satz gesperrt, aber durch den Timestamp sieht man ob der Zeitraum der Sperre Sinn macht. Wenn zu lange dann kann man den Satz überschreiben. Die Art wird bei mir benötigt um zu Unterscheiden ob z.B. ein User bei Artikel nur Stammdaten wie Bezeichnung, Texte etc. ändert oder ob bei der Fakturierung der letzte Verkauf, verkaufte Stückzahlen etc. geändert werden. Manche Änderungen können unabhängig gemacht werden und es muss keine Rücksicht darauf genommen werden ob jemand nur zur Stammdatenbearbeitung in einer anderen Bearbeitungsart den Satz sperrt.
Grüße
Rudolf
Benutzeravatar
satmax
1000 working lines a day
1000 working lines a day
Beiträge: 831
Registriert: Do, 02. Dez 2010 19:34
Wohnort: Biberbach in Österreich
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Logik im Netzwerk

Beitrag von satmax »

Ehrlich, warum sollte ein Timestamp in der Art nicht reichen (2016-01-08 10:21:01.938302 ) Die Wahrescheinlichkeit eines Lesefehlers auf der Platte ist da schon fast größer. :)

Ansonst, einfach einen Integerwert "Version", Diese Feld bei jedem Update um 1 hochzählen, am besten per Trigger, da kann keiner mehr vergessen. Ist das Maximum erreicht einfach wieder bei 1 beginnen. Vor dem Speichern prüfen ob Feld Version in DB <> Version im Speicher ist.
Gruß
Markus
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Logik im Netzwerk

Beitrag von AUGE_OHR »

hi,

ich denke das es keine Rolle spielt "wann" eine Änderung stattfand sondern "ob" es eine Änderung gab.

das 2 Leute zur selben Zeit den selben Record editieren wollen steht 2 : 86400.
wie ich sagte "könnte" der 2nd User auch 1 Std. später auf die Idee komme und wenn er "unwissend" ist ...
dazu muss man aber auf die "alten" geänderten Daten zugreifen (oder Logbuch) und dem User präsentieren ... die "Sperre" hat damit nichts zu tun.

die Felder DATUM/UHRZEIT habe ich in den meisten Fällen beim "Upgrade" nach PostgreSQL, deshalb verwende ich die weiter.
gruss by OHR
Jimmy
Benutzeravatar
satmax
1000 working lines a day
1000 working lines a day
Beiträge: 831
Registriert: Do, 02. Dez 2010 19:34
Wohnort: Biberbach in Österreich
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal
Kontaktdaten:

Re: Logik im Netzwerk

Beitrag von satmax »

AUGE_OHR hat geschrieben:hi,


das 2 Leute zur selben Zeit den selben Record editieren wollen steht 2 : 86400.
Aber nur wenn Du den Tag in Sekunden teilst. :) Der genannte Timestamp ist doch "etwas" genauer. :) :)

> 2016-01-08 10:21:01.938302
Gruß
Markus
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Logik im Netzwerk

Beitrag von georg »

Hallo,


vielleicht als Hintergrund meiner Überlegung: jemand ruft einen Datensatz auf und will ihn editieren. In diesem Moment wird der TIMESTAMP gelesen und gespeichert. Ein Problem mit der Zuordnung kann es nur geben, wenn exakt in der Mikrosekunde, wo der Datensatz gelesen wird, dieser nacheinander von zwei anderen Anwendern geändert wird, und für den Dialog wird die erste Version gelesen. Wir sprechen hier von einem gleichzeitigen Zugriff von DREI Anwendungen innerhalb der gleichen Mikrosekunde. Diese Wahrscheinlichkeit geht noch weiter gegen Null ...

Warum: weil es keine zwei Änderungen mit dem gleichen TIMESTAMP geben kann.

A liest um 2016-04-13 21:05:33:123456
B liest um 2016-04-13 21:07:22:987654

Selbst wenn beide in der gleichen Mikrosekunde ändern wollten, kann nur einer den Satz sperren und ändern. Sagen wir, B schafft es. Wenn A den Satz lesen und sperren kann, hat er bereits den TIMESTAMP von B's Änderung drin, und A's Änderung wird abgewiesen, weil der TIMESTAMP unterschiedlich ist.

Nach dem Editeren, vor dem Speichern, wird der gleiche Datensatz wieder (diesmal mit Sperre) gelesen und die TIMESTAMPs verglichen. Sind die TIMESTAMPs identisch, wurde der Datensatz zwischenzeitlich (konkurrierendes Update) nicht geändert, und die Änderungen des Anwenders können zurückgeschrieben werden.

Ja, ich stimme zu, dass ein Versionfeld, das über Trigger mitgezählt wird, auch eine sehr interessante Möglichkeit ist. Persönlich ziehe ich TIMESTAMP vor.

Für mich spricht für den TIMESTAMP, dass ich hier NICHTS unternehmen muss, damit dieser Aktualitätshinweis IMMER aktualisiert wird, da TIMESTAMP-Felder vom SQL-Server verwaltet und aktuell gehalten werden, ich muss sie nur als solche definieren.

Für mich spricht gegen den Trigger, dass dieser in der Datenbankdefinition vorhanden sein muss, und immer sichergestellt sein muss, dass bei einer Installation beim Kunden der Trigger auch vorhanden ist. Ist es das nicht, bleibt das Versionsfeld auf 0, und jede Änderung (auch konkurrierende) geht durch. Und dann kann es sehr seltsame Fehler geben, deren Ursache (nicht implementierter oder gelöschter Trigger) erst gefunden werden muss.

Es kommt also immer auf die Art der Anwendung an, und wieviel Traffic auf einzelne Datensätze entfällt. Für meinen Bereich ist der TIMESTAMP(6) optimal. Ob es für andere ebenfalls gilt, kann ich nicht sagen, denn: "Jede Jeck is anders".
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Logik im Netzwerk

Beitrag von Werner_Bayern »

Servus,

das mit dem Timestamp ist mir jetzt klar. Danke.

Ihr lasst also den Anwender immer munter Daten erfassen und im Fall der Fälle hat er einfach Pech gehabt und seine Daten werden verworfen?

Finde ich zumindest für meinen beschriebenen Fall nicht passend.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Logik im Netzwerk

Beitrag von AUGE_OHR »

Werner_Bayern hat geschrieben:Ihr lasst also den Anwender immer munter Daten erfassen und im Fall der Fälle hat er einfach Pech gehabt und seine Daten werden verworfen?
wieso "verworfen" ? [-X
nach dem Hinweis (Logfile) kann der User doch weiter entscheiden was passieren soll.

ein "Sperre" ist doch nur etwas "technisches" was bei PostgreSQL durch eine Transaktion (BEGIN / COMMIT ) automatisch geschieht.
worüber wir sprechen ist doch die Logik wenn User "Änderungen ändern" oder einen Auftrag doppelt eingeben/bearbeitet usw.
gruss by OHR
Jimmy
georg
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2823
Registriert: Fr, 08. Feb 2008 21:29
Hat sich bedankt: 95 Mal
Danksagung erhalten: 13 Mal

Re: Logik im Netzwerk

Beitrag von georg »

Guten Morgen, Werner -


ausgegangen bin ich von dieser Frage:
Werner_Bayern hat geschrieben: Wie macht man das am besten in SQL mit dem rlock?
und habe sie von der technischen Seite beantwortet. Es gibt aber immer auch noch die Philosophie, die der Programmierer vertritt. Da Du mit den gegebenen Antworten etwas unzufrieden bist, würde ich gerne eine Gegenfrage stellen:
Werner_Bayern hat geschrieben: 3. Wenn ok, DS wird erzeugt, Artikelnr. (PRIMARY KEY) wird gespeichert
Wie reagiert Dein Programm dem Anwender gegenüber, wenn es diese Artikelnummer schon gibt?
Werner_Bayern hat geschrieben:Ihr lasst also den Anwender immer munter Daten erfassen und im Fall der Fälle hat er einfach Pech gehabt und seine Daten werden verworfen?
Da hast Du mich (wohl) leider missverstanden: Die Änderungen des Anwenders können nicht übernommen werden. Wie das dem Anwender kommuniziert wird, und was gemacht wird (z.B. eine zweispaltige Darstellung der Daten, links die aktuellen Werte, rechts die vom Anwender eingegebenen Werte; alternativ kann man auch den Ursprungsdatensatz intern speichern und prüfen, ob die vom Anwender geänderten Felder unverändert sind und dann ohne Rückfrage speichern wenn es keinen Konflikt gibt) ist eine Entscheidung, die bei Dir als Programmierer liegt (oder vom Auftraggeber vorgegeben wird).

Kleines Beispiel gefällig?

Kundennummer: 123
Kundenname: Peter Müller
Kundenort: Köln
Kundentelefon: 0221-311355

Diese Daten stehen im Kundensatz, den der Mitarbeiter sieht, wenn er den Datensatz ändern will. Während er den Satz bearbeitet, nimmt ein anderer Anwender folgende Änderung vor:

Kundennummer: 123
Kundenname: Peter Müller
Kundenort: Köln-Deckstein
Kundentelefon: 0221-311355

Der Anwender ändert die Telefonnummer:

Kundennummer: 123
Kundenname: Peter Müller
Kundenort: Köln
Kundentelefon: 0221-311356

Diesen Konflikt kann ein Programm (theoretisch) selbständig lösen, da das Feld "Kundentelefon" im ursprünglichen und aktuellen Datensatz unverändert ist. Hat der Anwender aber ebenfalls den Ort geändert:

Kundennummer: 123
Kundenname: Peter Müller
Kundenort: Bonn
Kundentelefon: 0221-311356

kann der Konflikt nicht mehr vom Programm alleine gelöst werden.

Hier ist der Programmierer gefragt, wie er den Konflikt löst.
Werner_Bayern hat geschrieben:Ihr lasst also den Anwender immer munter Daten erfassen und im Fall der Fälle hat er einfach Pech gehabt und seine Daten werden verworfen?
Dazu noch ein Hinweis: ich habe auf der IBM S/38 Programme gesehen, die genau nach diesem Schema gestrickt waren. Die Bildschirmdateien waren falsch definiert, und wenn eine Eingabe fehlerhaft war, kam eine Fehlermeldung, und die ganzen Eingabefelder waren wieder leer. Das so etwas mehr als schlechter Stil ist, versteht sich von selbst, hoffe ich.
Liebe Grüsse aus der Eifel,

Georg S. Lorrig
Redakteur der Wiki des Deutschprachigen Xbase-Entwickler e.V.
Antworten