Update und Join Left

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
pjensen
Beiträge: 77
Registriert: Fr 27. Jul 2007, 08:43
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Nahe Flensburg

Update und Join Left

Beitrag von pjensen »

Hallo,

mit JOIN LEFT kombiniere ich 2 Tabellen und zeige diese in einem DBGrid an.
Ein DBEdit ist mit einem Datenfeld verbunden hiervon verbunden.

Wenn ich im DBEdit einen Wert verändere , erhalte ich die Fehlermeldung
"Cannot update a complex query with more than one table"

Jetzt hatte ich mysql von 3.23 auf 5.0 upgedatet, weil ich gelesen habe, dass dies erst ab Version 4.0.4 geht.

Nach dem update auf 5.0 müsste das doch eigentlich funktionieren, tuts aber nicht. :twisted:

Was mache ich falsch?

MfG, Peter

knight
Beiträge: 802
Registriert: Mi 13. Sep 2006, 22:30

Re: Update und Join Left

Beitrag von knight »

Bevor wir dir evtl. sagen können, was du falsch machst, solltest du uns zuerst sagen, was du machst (Auszüge aus dem Quelltext, SQL-Befehl, verwendete Versionen, Zugriffskomponenten usw.)

knight

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Update und Join Left

Beitrag von Socke »

Ich empfehle das Lesen - das hilft manchmal echt weiter.
knight hat geschrieben:Bevor wir dir evtl. sagen können, was du falsch machst, solltest du uns zuerst sagen, was du machst (Auszüge aus dem Quelltext, SQL-Befehl, verwendete Versionen, Zugriffskomponenten usw.)
Das hat er bereits.

Noch ein Zitat:
pjensen hat geschrieben:mit JOIN LEFT kombiniere ich 2 Tabellen und zeige diese in einem DBGrid an.

Wenn ich im DBEdit einen Wert verändere , erhalte ich die Fehlermeldung
"Cannot update a complex query with more than one table"
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

knight
Beiträge: 802
Registriert: Mi 13. Sep 2006, 22:30

Re: Update und Join Left

Beitrag von knight »

Socke hat geschrieben: Das hat er bereits.
Da habe ich wohl deine hellseherischen Fähigkeiten unterschätzt. Ich vermag nicht zu erkennen, mit welchen Zugriffskomponenten (sqldb?) gearbeitet wird. Auch habe ich nicht erkennen können, wie der geänderte Wert in die Datenbank zurückgeschrieben werden soll. Und ob eine aktuelle Lazarus/FPC-Version verwendet wird, ist auch nicht bekannt. Um so brennender interessiert mich natürlich deine Fehleranalyse.

knight

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Update und Join Left

Beitrag von Socke »

knight hat geschrieben:
Socke hat geschrieben: Das hat er bereits.
Da habe ich wohl deine hellseherischen Fähigkeiten unterschätzt. Ich vermag nicht zu erkennen, mit welchen Zugriffskomponenten (sqldb?) gearbeitet wird. Auch habe ich nicht erkennen können, wie der geänderte Wert in die Datenbank zurückgeschrieben werden soll. Und ob eine aktuelle Lazarus/FPC-Version verwendet wird, ist auch nicht bekannt. Um so brennender interessiert mich natürlich deine Fehleranalyse.

knight
Ich hab extra im Zweiten Zitat ein wenig fett hervorgehoben...
Mit den Lazarus-Datenbank-Komponenten bzw. mit TDataset (als Basisklasse für alle Datenbankzugriffe/-queries) kann man zwar so viele Tabellen mittels JOIN miteinander verbinden, auslesen und darstellen, aber das Schreiben geht nicht mehr, weil TDataset nicht weiß, welche Tabelle konkret verändert werden muss. Die Fehlermeldung sagt einfach aus, dass man den Schreibzugriff nur verwenden kann, wenn man nicht mehr als eine Tabelle benutzt.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

pjensen
Beiträge: 77
Registriert: Fr 27. Jul 2007, 08:43
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Nahe Flensburg

Re: Update und Join Left

Beitrag von pjensen »

Oooops,

in der Tat hätte ich mehr Infos geben können:

SUSE 11.1 / KDE / Lazarus 09.26.2 beta , FPC 2.2.4, ZEOS 6.6.2.

Hier die relevante Procedure:

Code: Alles auswählen

Procedure TForm1.AblesewerteFiltern;
var F1,S1,S2 : String;
  i         : integer;
  AblDate   : String;
  ID_Geraet : Integer;
  JStr      : string;
  AbrJahr   : String;
  LStr      : String;
  ZStr      : String;
  SStr      : String;
  FStr      : String;
  WStr      : String;
 
 
Begin
  SStr:=(' Ablesewerte.ID,Nutzer.NutzerNr,Geraete.Raum,Nutzer.Nachname,Geraete.GeraeteNr,Geraete.Faktor,Ablesewerte.Ablesewert,Ablesewerte.Ablesedatum ');
  FStr:=(' FROM Geraete LEFT JOIN Ablesewerte ON (Geraete.ID=Ablesewerte.ID_Geraet) LEFT JOIN Nutzer ON (Geraete.ID_Nutzer=Nutzer.ID)');
  LStr:=(ZQuery_Liegenschaften.FieldByName('ID').AsString);
  JStr:=(ZQuery_Liegenschaften.FieldByName('AbrJahr').AsString);
  ZQuery_Ablesewerte.SQL.Text:='SELECT '+SStr+FStr+ ' WHERE Nutzer.Historie = 0 AND Geraete.ID_Liegen='+LStr+' AND  Ablesewerte.AbrJahr='+JStr;
  ZQuery_Ablesewerte.Active:=True;
//  showstring(ZQuery_Ablesewerte.SQL.Text);
end;
OK, es sind also 3 Tabellen :wink:


DBgrid: Im Objektinspektor steht bei Datasource: Datasource_Ablesewerte
ZQuery: Im Objektinspektor steht bei Dataset: ZQuery_Ablesewerte.

Im Moment mache ich es folgendermaßen:
In einem TEdit trage ich einen Wert ein und eine 2.te ZQuery updatet dann die Tabelle Ablesewerte. (nur diese allein).
Anschließend wird ZQuery_Ablesewerte refresht.
Das geht mit mysql 3.23 und 5.0 ganz gut, ist aber recht aufwendig, insbsondere wenn noch diverse ähnliche Sachen geplant sind.
(Diverse andere Join und Tabellenupdates)

Ich möchte lieber statt des TEdt eine TDBEdit nehmen und direkt ohne 2.tes ZQuery die Werte ändern
.

Dazu hatte ich u.a. folgendes gelesen:
http://www.issociate.de/board/post/1878 ... ellen.html" onclick="window.open(this.href);return false;

Sinngemäß ähnliches findet man auch an vielen anderen Stellen im Netz.
Fazit:
Starting with MySQL 4.0.4, you can also perform UPDATE operations
that cover multiple tables.
ist zu beachten.

Deswegen hatte ich den mysql-server auf 5.0 upgedatet.
Trotzdem bekomme ich den anfänglich genannten Fehler.

Also: Mache ich etwas falsch oder geht es trot Serverupdate nicht( z.B. wegen fpc, Zeoa oder sonstigen)?

MfG, Peter
Zuletzt geändert von monta am Mo 12. Okt 2009, 14:56, insgesamt 1-mal geändert.
Grund: Codehighlighter

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Update und Join Left

Beitrag von mse »

pjensen hat geschrieben: Also: Mache ich etwas falsch oder geht es trot Serverupdate nicht( z.B. wegen fpc, Zeoa oder sonstigen)?
Es geht nicht weil ZQuery_Ablesewerte aus der komplexen Abfrage die update-statements nicht automatisch erzeugen kann. Da ich Zeos zu wenig gut kenne, muss dir jemand anderes weiterhelfen. Für MSEgui wüsste ich die Lösung...

Martin

pjensen
Beiträge: 77
Registriert: Fr 27. Jul 2007, 08:43
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Nahe Flensburg

Re: Update und Join Left

Beitrag von pjensen »

Code: Alles auswählen

TDBEdit_Blah_...onexit..
 
begin...
   ZQuery_Ablesewerte.SQL.Text:=('UPDATE Ablesewerte SET Ablesedatum = "'+DatStr+'" WHERE ID = '+EingabeID);
   ZQuery_Ablesewerte.ExecSQL;
   ShortDateFormat := 'dd.mm.yyyy';
   AblesewerteFiltern;     
...
end
so gehts auch, "ZQuery_Ablesewerte.update..." geht allerdings nicht.

MSE würde mich schon mal interessieren, allerdings nicht bei diesme projekt, das ist schion zu weit fortgeschritten....

@ mse: Heißt Du zufällig Schreiber?

MfG, Peter
Zuletzt geändert von monta am Mo 12. Okt 2009, 14:56, insgesamt 1-mal geändert.
Grund: Codehighlighter

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Update und Join Left

Beitrag von mse »

pjensen hat geschrieben: @ mse: Heißt Du zufällig Schreiber?
Ja.

martin_frb
Beiträge: 588
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Update und Join Left

Beitrag von martin_frb »

Es könnte sein das sich das auf der Seite von mysql durch einen VIEW ( http://dev.mysql.com/doc/refman/5.0/en/create-view.html" onclick="window.open(this.href);return false; ) lösen lässt.

Bin mir aber nicht 100% sicher. Laut http://dev.mysql.com/doc/refman/5.0/en/ ... ility.html" onclick="window.open(this.href);return false; "certain join" => Es gibt views mit join die updatable sind, andere sind es nicht.

für ZEOS oder die Applikation sieht es dann so aus als gäbe es nur eine Tabelle, und daher sollte es von der Seite gehen.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Update und Join Left

Beitrag von mse »

Ich habe es zwar nie ausprobiert, aber meines Wissens braucht es eine TZUpdateSQL Komponente mit entsprechenden Delete., Modify- und InsertSQL statements welche in TZQuery.UpdateObject ausgewählt wird.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6869
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Update und Join Left

Beitrag von af0815 »

Prinzipell lassen sich komplexere Datenmengen nur dann updaten, wenn

-> von jeder Tabelle der Primary Key vorhanden ist
-> die geänderte Spalte nicht im Join vorkommt
-> die geänderten Spalten aus einer Tabelle sind

und der (lokale) Parser das Statement auch zerlegen kann. Zusätzlich muß der DB Server natürlich mitspielen.
Ein schöner Ausweg ist natürlich die Update, Delete und Insertstatements zu verwenden, denn dann hat man es natürlich in der Hand die Änderungen sicher hinüberzubringen.

Wenn man die Statements nicht selbst nicht schreiben kann, dann würde ich auch von komplexeren Statement die Finger lassen und dafür ein paar Queries mehr verwenden. Da kann man zumindest dann den Überblick bewahren.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

pjensen
Beiträge: 77
Registriert: Fr 27. Jul 2007, 08:43
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Nahe Flensburg

Re: Update und Join Left

Beitrag von pjensen »

Mal auf die Schnelle ausprobiert::

Das VIEW-updaten von martin_frb mit dem VIEW funktioniert tatsächlich.
UPDATE im DBEdit funktioniert ohne weiteres, die Werte werden auch in der "Ausgangstabellle" geupdatet.

Nächste Frage:

Erstellt man eine VIEW üblicherweise einmal und nutzt diese dann wie eine Tabelle?
Das würde ja bedeuten, dass man im Prog-Code diese VIEW gar nicht erstellt, sondern diese nur nutzt, also genau wie eine Tabelle behandelt.
(siehe unten, nur die beiden letzten Zeilen sind nicht auskommentiert mit //).


Noch eine Frage:
Man kann eine nicht vorhandene VIEW nicht löschen, es gibt eine Fehlermeldung. (DROP VIEW VIEW1)
Wie löscht man diese bei Bedarf, wenn man nicht weiß, ob diese vorhanden ist oder nicht.

Gibt es eine MySQL-Befehlt der sinngemäß lautet ' IF EXIST VIEW1 THEN DROP VIEW VIEW1 " oder so?


MfG, Peter


Code: Alles auswählen

Begin
  SStr:=('Ablesewerte.ID, Nutzer.NutzerNr, Geraete.Raum, Nutzer.Nachname, Geraete.GeraeteNr, Geraete.Faktor, Ablesewerte.Ablesewert, Ablesewerte.Ablesedatum ');
  FStr:=(' FROM Geraete LEFT JOIN Ablesewerte ON (Geraete.ID=Ablesewerte.ID_Geraet) LEFT JOIN Nutzer ON (Geraete.ID_Nutzer=Nutzer.ID)');
 
  LStr:=(ZQuery_Liegenschaften.FieldByName('ID').AsString);
  JStr:=(ZQuery_Liegenschaften.FieldByName('AbrJahr').AsString);
 
  ZQuery_Ablesewerte.SQL.Text:='SELECT '+SStr+FStr+ ' WHERE Nutzer.Historie = 0 AND Geraete.ID_Liegen='+LStr+' AND  Ablesewerte.AbrJahr='+JStr;
  ZQuery_Ablesewerte.Active:=True;
 
//  ZQuery1.SQL.Text:='DROP VIEW VIEW1';
//  ZQuery1.ExecSQL;
 
//  ZQuery1.SQL.Text:=' CREATE VIEW VIEW1 AS SELECT Ablesewerte.AbrJahr, Nutzer.Historie, Geraete.ID_Liegen, '+SStr+FStr;
//  showstring(ZQuery1.SQL.Text);
//  ZQuery1.ExecSQL;
 
  ZQuery1.sql.Text:='SELECT * FROM VIEW1 WHERE Historie = 0 AND ID_Liegen= '+LStr+' AND  AbrJahr='+JStr;
  ZQuery1.Active:=True;
 
end;
Zuletzt geändert von monta am Mo 12. Okt 2009, 14:57, insgesamt 1-mal geändert.
Grund: Codehighlighter

martin_frb
Beiträge: 588
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Update und Join Left

Beitrag von martin_frb »

1) Also zunächst empfehle ich dazu die docs at mysql zu lesen
http://dev.mysql.com/doc/refman/5.0/en/ ... ition.html" onclick="window.open(this.href);return false;
(auch in deutsch, aber scheint unvollstaendig) http://dev.mysql.com/doc/refman/5.1/de/ ... ition.html" onclick="window.open(this.href);return false;

2) drop view if exists some_view_name;
oder
create or replace view xxxxx as ....

martin_frb
Beiträge: 588
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Update und Join Left

Beitrag von martin_frb »

pjensen hat geschrieben:Mal auf die Schnelle ausprobiert::
Erstellt man eine VIEW üblicherweise einmal und nutzt diese dann wie eine Tabelle?
Das würde ja bedeuten, dass man im Prog-Code diese VIEW gar nicht erstellt, sondern diese nur nutzt, also genau wie eine Tabelle behandelt.
(siehe unten, nur die beiden letzten Zeilen sind nicht auskommentiert mit //).
Wuerde ich so machen, einmal erstellen, und gut ist.

Antworten