AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Meldung "0 record(s) updated. Only one record should have been updated"
Thema durchsuchen
Ansicht
Themen-Optionen

Meldung "0 record(s) updated. Only one record should have been updated"

Ein Thema von erich.wanker · begonnen am 10. Sep 2020 · letzter Beitrag vom 10. Sep 2020
Antwort Antwort
Benutzerbild von erich.wanker
erich.wanker

Registriert seit: 31. Jan 2008
Ort: im schönen Salzburger Land
461 Beiträge
 
Delphi XE4 Professional
 
#1

Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 13:16
Datenbank: mySQL • Version: 5.7.29 - MySQL Community Server (GPL) • Zugriff über: Zeos 7.2.6-stable
Hallo Leute,

ich bekomme Fehler 0 record(s) updated. Only one record should have been updated.

wenn ich auf mehreren Clients (mit meiner Software) auf die Mysql Datenbank am Server zugreife.

Solange ich nur eine Client-App starte gibt es keine Probleme.


Jede Tabelle hat ein Primary Field (id)


Verbinden tu ich jeden Client mit einer Zconnection

Code:
object ZConnection1: TZConnection
    ControlsCodePage = cCP_UTF16
    AutoEncodeStrings = True
    Catalog = ''
    Properties.Strings = (
      'controls_cp=CP_UTF16'
      'CLIENT_FOUND_ROWS=1'
      'AutoEncodeStrings=ON')
    TransactIsolationLevel = tiReadCommitted
    HostName = ''
    Port = 3306
    Database = 'datenbank'
    User = 'karotte'
    Password = ''
    Protocol = 'mysqld-5'
    LibraryLocation = 'C:\Server\htdocs\libmysql.dll'
    Left = 52
    Top = 28
  end

Jedes ZQuery hat "wmWhereKeyOnly" als WhereMode und "umUpdateChanged" als UpdateMode (CachedUpdates = false) ShowRecordTypes =[usUnmodified,usModified,usInserted]


Meine Typischen SQL´s schauen so aus:


Code:
  ZQuery.SQL.Clear;
  ZQuery.SQL.append('SELECT * FROM tabelle where `Dings` = "' + stringvariable + '" ');
  ZQuery.Open;

  if ZQuery.RecordCount > 0 then
    begin
      ZQuery.Edit;
      ZQuery.fieldbyname('Feld').Asinteger := 12345;
      ZQuery.Post;
    end;

Hat jemand eine Idee wieso ich den Fehler bekomme?

Danke für Hinweise

Erich
Erich Wanker - for life:=1971 to lebensende do begin ..
O
/H\
/ \

Geändert von erich.wanker (10. Sep 2020 um 13:53 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.508 Beiträge
 
Delphi 7 Professional
 
#2

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 14:36
Schlüsselverletzung: (Constraint oder eindeutiger Index)

Irgendwer vergibt für ID im Primary Field (id) einen Werte, der schon in der Tabelle vorhanden ist.

Es hätten mit diesem Wert mehrere Datensätze aktuallisiert werden müssen, es dürfte aber nur ein Datensatz aktuallisiert werden, deshalb wird kein Datensatz aktuallisiert, sondern diese Fehlermeldung ausgegeben.

Nach welcher Logik wird denn die ID vergeben?

Automatisch von der Datenbank per AutoInc, Sequenz, ... oder macht das jeder Client für sich aus?

Desweiteren:
Delphi-Quellcode:
  ZQuery.SQL.Clear;
  ZQuery.SQL.append('SELECT * FROM tabelle where `Dings` = "' + stringvariable + '" ');
  ZQuery.Open;

  if ZQuery.RecordCount > 0 then
    begin
      ZQuery.Edit;
      ZQuery.fieldbyname('Feld').Asinteger := 12345;
      ZQuery.Post;
    end;
Wenn RecordCount > 0 können im Ergebnis 1 bis n Datensätz enthalten sein.
Beim Post muss nun was aktuallisiert werden, aber für Zeos bzw. die Datenbank reichen die Informationen im Datensatz nicht aus, um eindeutig einen Datensatz in der Datenbank zu identifizieren, der von der Änderung betroffen sein soll. Es wären mit den Datensatzinfos demnach <> 1 Datensätze zu ändern, also entweder 0 oder n, wobei n größer 1 ist.

Das passiert gerne dann, wenn man auf einem Client 1 einen Datensatz ändert und ein Client 2 den gleichen Datensatz zwischenzeitlich geändert hat. Der zwischenzeitlich von Client 2 geänderte Datensatz enthält nicht mehr die gleichen Informationen, wie der von Client 1 gerade zu bearbeitende / speichernde Datensatz. Deshalb scheitern Zeos und / oder Datenbank beim Speichern der Änderungen. Resultat: Deine Fehlermeldung aus dem Threadtitel.

Das passiert gerne, wenn die Transaktionssteuerung nicht so ganz sauber funktioniert (oder fehlt).

Es passiert aber auch gerne, wenn man keine eigene Transaktionssteuerung implementiert hat und in der TZConnection AutoCommit auf true steht.
Wer zuerst speichert gewinnt, der oder die Anderen bekommen Deine Fehlermeldung aus dem Threadtitel.

Weitere Ursachen möglich? Will ich mal nicht ausschließen.
  Mit Zitat antworten Zitat
Benutzerbild von erich.wanker
erich.wanker

Registriert seit: 31. Jan 2008
Ort: im schönen Salzburger Land
461 Beiträge
 
Delphi XE4 Professional
 
#3

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 14:54
Hallo

die "id" wird durch die Datenbank gestellt

Code:
  // ---------------- so schauts bei allen Tabellen aus
  try
    begin
      Z1.SQL.Clear;
      Z1.SQL.append('SELECT `id` FROM `meine_tabelle`');
      Z1.Open;
    end;
  except
    begin
      ASQL := 'CREATE TABLE `meine_tabelle` (' + ' `id` INT(8) UNSIGNED AUTO_INCREMENT PRIMARY KEY,'

TZConnection AutoCommit ist auf true

..

Was ich nicht ganz verstehe:
Wenn USER_A einen neuen Datensatz via ZQuery -append - post schreibt ( und die id automatisch vergeben wird)
wieso kann dann USER_B auf einmal keinen neuen Datensatz ( via ZQuery -append - post) mehr schreiben??
Erich Wanker - for life:=1971 to lebensende do begin ..
O
/H\
/ \

Geändert von erich.wanker (10. Sep 2020 um 15:05 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.508 Beiträge
 
Delphi 7 Professional
 
#4

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 15:29
Wenn AutoCommit auf True steht, gehe ich mal davon aus, dass Du kein eigenes Transationshandling im Programm hast.

Wenn also zwei Clients (mehr oder weniger) zeitgleich eine Transaktion starten, dann sehen sie quasi den gleichen Datenbestand. Wenn nun ein Client seine Transaktion per AutoCommit beendet, hat er einen neuen Datenbestand. Der Client, der seine Transaktion noch nicht beendet hat, hat weiterhin seinen alten Datenbestand. Will er nun seine Transaktion schließen, weiß er nicht, was der andere Client bereits geeändert hat und speichert daher seine Daten. Die Datenbank weiß jedoch, dass sein Datenbestand von dem des anderen Clients abweicht. Für sie kann dadurch ein Konflikt entstehen.

Wenn Client 1 den Datensatz mit ID = 1 ändert und dort als Namen z. B. Müller eingibt, während Client 2 gleichzeitig den Datensatz mit ID 1 ändert und dort als Namen z. B. Meier eingibt: Wessen Daten sollen in der Datenbank stehen? Die von Client 1, weil er den Datensätz zuerst zum Ändern aufgerufen hat oder die Daten von Client 2, weil er zuerst gespeichert hat?
Oder sollen die Daten von Client 2 kommentarlos überschrieben werden, obwohl Client 1 nicht weiß, was Client 2 geändert hat?

Wollen mehrere Clients einen Datensatz ändern und die Transaktionen überschneiden sich, so wird es immer zu einem Fehler kommen. (U. a. dafür sind Transaktionen da.)
Code:
Client 1 - Start der Transaktion
Client 1 - lesen des Datensatzes
Client 2 - Start der Transaktion
Client 2 - lesen des Datensatzes
Client 1 - ändern des Datensatzes
Client 2 - ändern des Datensatzes
Client 2 - speichern des Datensatzes
Client 1 - speichern des Datensatzes
Client 2 - Commit
Client 1 - Commit
Was soll jetzt in der Datenbank stehen?
Die Änderung von Client 2, weil er zuerst das Commit gemacht hat?
Die Änderung von Client 1, weil er zuletzt das Commit gemacht hat?

Und nun das Ganze nochmal mit 25.811 Clients?

Wer soll da wann unter welchen Voraussetzungen gewinnen?

Fehlermeldung abfangen und darauf hinweisen, dass der Datensatz zwischenzeitlich anderweitig geändert wurde.
Anzeige der Änderungen anbieten, um dann mit den geänderten Daten weiterzuarbeiten oder Änderungen verwerfen (Rollback).
  Mit Zitat antworten Zitat
Benutzerbild von erich.wanker
erich.wanker

Registriert seit: 31. Jan 2008
Ort: im schönen Salzburger Land
461 Beiträge
 
Delphi XE4 Professional
 
#5

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 15:38
Vielen Dank für die ausführliche Hilfe. Ich bin momentan echt am verzweifeln ..

Bei "edit" würde ich ja noch verstehen dass ich irgendwie ein Problem bekomme ..

Aber ich bekomme auch bei neu zu erstellenden Datensätze diese Meldung


User 1 startet per onClick eines Buttons folgende Procedure:

ZQuery.Append;
ZQuery.fieldbyname('xx').asstring = yy
ZQuery.Post;

Wenn nun User 2 die gleiche Procedure aufruft kommt schon der Fehler ..

Wenn aber User 2 (nachdem user 1 gepostet hat) - die Software neu startet GEHTS WIEDER

P.S.:
Habe kein eigenes Transationshandling
Der zuletzt Posted - dessen Wert soll drinnen stehen.
Erich Wanker - for life:=1971 to lebensende do begin ..
O
/H\
/ \
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.508 Beiträge
 
Delphi 7 Professional
 
#6

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 15:59
Multiuserbetrieb ohne eigenes Transaktionshandling ist suboptimal.

Wenn Client 1 eine Transaktion startet, dann ist der nächste Wert für das AutoInc bekannt.
Wenn Client 2 eine Transaktion startet, dann ist der nächste Wert für das AutoInc bekannt.

Wenn sie das beide gleichzeitig machen, dann haben sie beim Speichern auch den gleichen Wert.

Wenn nun Client 1 zuerst speichert, dann wird der Wert vergeben.
Wenn nun Client 2 speichert, wird der gleiche Wert vergeben.

Pech gehabt: Doppelter Wert für die ID vergeben.
Resultat: Fehlermeldung.

Edit heißt nur: Das in Delphi die Daten geändert werden sollen.
Post heißt: Daten ab zur Datenbank. Dort tritt dann der Fehler auf.
Wie soll die Datenbank denn beim Edit schon wissen, dass es nach der Änderungen beim Speichern ein Problem geben könnte?

Noch witziger wird es dann beim Append:
Woher soll die Datenbank denn dort wissen, was als Daten eingegeben wird und später beim Post zu einem Problemführen könnte? Globalgalaktische ?

Programm beende macht letztlich (meist) ein Rollback.

Kann man sinnvoller selbst im Progamm steuern und ist dort für den Anwender weniger lässtig
  Mit Zitat antworten Zitat
Benutzerbild von erich.wanker
erich.wanker

Registriert seit: 31. Jan 2008
Ort: im schönen Salzburger Land
461 Beiträge
 
Delphi XE4 Professional
 
#7

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 16:48
@Delphi.Narium - vielen Dank für die ganzen Infos und für die hochprofessionelle Hilfestellung.
Vielen herzlichen Dank und ENTSCHULDIGUNG für die ganze Unannehmlichkeiten ....

Ich hab ja überall ein Feld "id" was automatisch mit einer Nummer gefüllt ist ..

Ich hab aber auch überall ein Feld "inr" was ich beim "append" händisch fülle ...

nach jedem Append - egal welche Tabelle) habe ich überall einen Einzeiler: ZQuery.fieldbyname('inr').asinteger:=new_id;



Delphi-Quellcode:
function TUniMainModule.new_id: Integer;
var
* i: Integer;
begin
* GET_INR.Refresh;* * * * * * <-------- THIS SOLVED MY PROBLEM !!!!!!!

* i := GET_INR.fieldbyname('id').Asinteger;
* i := i + 1;
* GET_INR.Edit;
* GET_INR.fieldbyname('id').Asinteger := i;
* GET_INR.Post;

* Result := i;
end;
...das GET_INR.Refresh; war die Lösung


Vielen Dank
und liebe Grüße
Erich

P.S.: Gesund bleiben
Erich Wanker - for life:=1971 to lebensende do begin ..
O
/H\
/ \
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 19:01
Wir verwenden dafür (bei MariaDB) Generatoren. Damit wird der Wert erst beim Schreiben generiert und somit ist es egal wie lange die Transaktion vorher offen war.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
EgonHugeist

Registriert seit: 17. Sep 2011
187 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 19:02
Hallo Erich,
zusätzlich schau da mal rein: https://sourceforge.net/p/zeoslib/tickets/270/
gleiches kann bei updates passieren, deswegen mal https://dev.mysql.com/doc/refman/8.0...cted-rows.html anschauen.
Ps. ich hab 7.3(wird 8.0) in den beta modus gesetzt. Hab Spaß!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: Meldung "0 record(s) updated. Only one record should have been updated"

  Alt 10. Sep 2020, 19:22
GET_INR.Refresh; <-------- THIS SOLVED MY PROBLEM !!!!!!!
Per se bleibt das Problem bestehen, auch wenn die kritische Zeit verkürzt wurde und somit die Wahrscheinlichkeit etwas sinkt, dass das Problem beobachtet wird.
$2B or not $2B
  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 14:14 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