AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken UniDac Select & Edit (Anfängerfrage)
Thema durchsuchen
Ansicht
Themen-Optionen

UniDac Select & Edit (Anfängerfrage)

Ein Thema von sundance · begonnen am 4. Dez 2013 · letzter Beitrag vom 5. Dez 2013
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von sundance
sundance

Registriert seit: 9. Mai 2006
98 Beiträge
 
Delphi 7 Professional
 
#1

UniDac Select & Edit (Anfängerfrage)

  Alt 4. Dez 2013, 10:03
Datenbank: MySQL • Version: 5 • Zugriff über: UniDAC
Hallo zusammen,

ich teste gerade die UniDAC-Komponenten (wir möchten unsere firmeninterne Applikation (Kommandozeilenprogramm) als Stand-alone exe ohne zusätzliche DLL ausliefern).

Der erste Test besteht darin, einen Datensatz einzulesen, ein paar Felder abzuändern und wieder zurückzuschreiben.
Ich habe das so gemacht (die try/except-Blöcke habe ich hier weggelassen):
Delphi-Quellcode:
uniConn := TUniConnection.Create(nil);
uniQuery := TUniQuery.Create(nil);

try
  // Datenbankverbindung
  uniConn.Server := dbHost;
  uniConn.Port := 3306;
  uniConn.Username := dbUser;
  uniConn.Password := dbPassword;
  uniConn.Database := dbName;
  uniConn.ProviderName := TMySQLUniProvider.GetProviderName;
  uniConn.Open;

  // Abfrage
  uniQuery.Connection := uniConn;
  uniQuery.SQL.Text := Format('SELECT * FROM %s WHERE hostname=''%s''',[dbTable, ComputerName]);
  uniQuery.Open; // Datenbankabfrage durchführen
  uniQuery.First; // und auf erstem Datensatz positionieren
  if not uniQuery.Eof then begin
    stUser := uniQuery.FieldByName('username').AsString;
    expDate := uniQuery.FieldByName('reset_date').AsDateTime;

    // Felder aktualisieren
    uniQuery.Edit;
    uniQuery.FieldByName('last_update').AsDateTime := Now;
    uniQuery.Post;
  end;
  uniQuery.Close;

finally
  uniConn.Free;
  uniQuery.Free;
end;
Beim "uniQuery.Post" gibt's dann eine Exception (Fehler in SQL-Statement near "index=3234").
"index" ist ein AutoIncrement-Feld in der Tabelle und kann natürlich nicht geschrieben werden.

Fragen:
- Stimmt meine Vorgehensweise prinzipiell mit Edit/Post?
- Wie kann man das zum Server geschickte SQL-Statement überprüfen?
- Was ist zu tun bzgl. des Fehlers mit "index"? Kann das Feld vor dem Post entfernt werden?

Ich weiß, dass es auch bei UniDAC ein Forum gibt - aber die Experten sind nun mal hier...

.sundance.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#2

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 4. Dez 2013, 11:29
An deinem Code ist soweit alles richtig.
4 Kleinigkeiten:
Delphi-Quellcode:
// QuotedString statt ''
uniQuery.SQL.Text := Format('SELECT * FROM %s WHERE hostname=%s',[dbTable, QuotedString(ComputerName)]);
Delphi-Quellcode:
uniQuery.Open; // Datenbankabfrage durchführen
// nach einem Open steht die Datenmenge immer auf dem 1. Datensatz (aber nur wenn die Menge zuvor geschlossen war)
// uniQuery.First; // und auf erstem Datensatz positionieren - braucht man nicht
Eof nimmt man wenn man durch das Dataset iterieren möchte
Um zu prüfen ob überhaupt Datensätze vorhanden sind verwendet man IsEmpty
Delphi-Quellcode:
// if not uniQuery.Eof then begin
if not uniQuery.IsEmpty then begin
Beim beschreiben der Felder kann man die kürzere Schreibweise verwenden.
Beim Lesen sollte man es aber die AsXXXXX-Methoden verwenden um eine Ungültige Variantumwandlung Exception zu vermeiden
Delphi-Quellcode:
// Felder aktualisieren
uniQuery.Edit;
uniQuery['last_update'] := Now; // kürzer und "schöner" (ist aber auch Geschmacksache)
uniQuery.FieldByName('last_update').AsDateTime := Now;
uniQuery.Post;
Jetzt nur zu deinem Problem mit dem Autoincrementfeld "index".
Die VCL muss wissen dass das Autoincfeld nicht upgedatet werden darf.
Prüfe mal welchen Inhalt uniQuery.FieldByName('index').ProviderFlags hat.
Notfalls muss man von Hand eingreifen und die Flags ändern.
Eigentlich müsste das UniDAC schon richtig machen (alte Version?)
fork me on Github
  Mit Zitat antworten Zitat
Benutzerbild von sundance
sundance

Registriert seit: 9. Mai 2006
98 Beiträge
 
Delphi 7 Professional
 
#3

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 4. Dez 2013, 12:45
Hallo sx2008,

vielen Dank für deine Tipps (ist echt deutlich schlanker... Schade, dass die Doku da ein wenig mager ist).
Vor dem Aufruf von "Post" haben die ProviderFlag folgenden Inhalt: [pfInUpdate..pfInWhere]
(hab's mal auf [pfHidden] gesetzt -> keine Veränderung)

Alte Version ist nicht der Fall (ist vom September 2013)

.sundance.

Geändert von sundance ( 4. Dez 2013 um 13:16 Uhr)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#4

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 4. Dez 2013, 15:04
Hallo,

warum nicht in etwa so:
Delphi-Quellcode:
uniQuery.SQL.Text := Format('update %s set last_update = %f WHERE hostname = %s',[dbTable,now,QuotedString(ComputerName)]);
uniQuery.ExecSql;
Damit kommt "niemand" auf die Idee, index zu aktualisieren.
Mein Erfahrung aus den letzten "Jahrzehnten" ist, dass das Update einer Tabelle via Query, Edit und Post nicht bei allen Datenbanken immer reibungslos funktioniert.

In Deinem Fall versucht die Query (vermutlich) alle mit "Select * from" geholten Spalten per Post in die Datenbank zu schreiben. Sie "weiß" nicht, das index nicht geschrieben werden darf, dies "weiß" nur die Datenbank. Daraus dürfte der auftretende Fehler resultieren.

Das direkte Update dürfte auch schneller sein, als erst die Daten zu holen, dann im Programm zu ändern und dann zu schreiben. Mit dem Update ist exakt ein Datenbankzugriff erforderlich.
  Mit Zitat antworten Zitat
Benutzerbild von sundance
sundance

Registriert seit: 9. Mai 2006
98 Beiträge
 
Delphi 7 Professional
 
#5

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 4. Dez 2013, 15:40
Hallo Stephan,

der Gedanke mit ExecSQL ist mir auch schon durch den Kopf gegangen, und wäre auch bestimmt nicht komplizierter als Edit/Post. Aber im Beispiel ist es nur ein Feld, welches aktualisiert werden muss - in der "echten" Anwendung sind es aber deutlich mehr (5-10) und da wird der "Zusammenbau" des SQL-Statements doch etwas unübersichtlicher.

Ich habe mittlerweile auch von Devart eine Lösung für das index-Problem erhalten:
Zitat:
The point is that the INDEX is a MySQL reserved word. To avoid the problem, you should set the QuoteNames option to True. Here is a code example:
uniQuery.Options.QuoteNames := True;
Damit funktioniert es problemlos...

Aber wahrscheinlich muss ich noch aus einem anderen Grund auf die ExecSQL-Variante ausweichen, um anstelle der Delphi-Funktion Now die aktuelle Serverzeit einzutragen (über die mySQL-Funktion NOW()). Leider kann ich mir das vorherige Einlesen hier nicht sparen, weil (in der "echten" Anwendung) einige Felder vor dem Update ausgewertet werden müssen...

.sundance.

Geändert von sundance ( 4. Dez 2013 um 15:45 Uhr)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#6

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 4. Dez 2013, 15:53
Hallo .sundance.,

stimmt, "index" ist ein reserviertes Wort, da hätte ich auch drauf kommen können

Warum sollte ein
Delphi-Quellcode:
uniQuery.SQL.Text := Format('update %s set spalte1 = %s,
spalte2 = %s, ... spalteN = %s WHERE hostname = %s
',[dbTable,wert1,wert2,...,wertN,QuotedString(ComputerName)]);
uniQuery.ExecSql;
komplizierte sein, als ein
Delphi-Quellcode:
    uniQuery.Edit;
    uniQuery.FieldByName('spalte1').AsString := wert1;
    uniQuery.FieldByName('spalte2').AsString := wert2;
     ...
    uniQuery.FieldByName('spalteN').AsString := wertN;
    uniQuery.Post;
?

Querys kann man parametrisieren, schau mal nach ParamByName...

Könnte dann in etwa so aussehen:
Delphi-Quellcode:
uniQuery.SQL.Text := Format('update %s set spalte1 = :spalte1,
spalte2 = :spalt2, ... spalteN = :spalteN WHERE hostname = %s
',[dbTable,QuotedString(ComputerName)]);
uniQuery.ParamByName('spalte1').AsString := wert1;
uniQuery.ParamByName('spalte2').AsString := wert2;
...
uniQuery.ParamByName('spalteN').AsString := wertN;
uniQuery.ExecSql;
Und auch hier ist dann nur ein schreibender Zugriff auf die Datenbank notwendig und nicht erst lesen und dann schreiben.
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#7

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 4. Dez 2013, 17:42
INDEX is a MySQL reserved word
Aus diesem Grund habe ich mir bereits vor langer Zeit angewöhnt, die Index-Spalte einer Tabelle stets mit dem Tabellen-Namen zu verbinden, z.B. Idx_Adressen, Idx_Kategorie usw. Nach Möglichkeit sollte man Tabellen- und Spaltennamen mit aussagekräftigen Bezeichnern versehen, um die Lesbarkeit erhöhen. Hat man sich erst einmal an ein bestimmtes Schema gewöhnt, entfällt oft auch das Nachschlagen bzw. Suchen eines Spalten- oder Tabellennamens, denn der ergibt sich dann oft von selbst. Ich weiß also, daß z.B. meine Index-Spalten immer mit Idx_ beginnen und kann so viel flüssiger arbeiten.
  Mit Zitat antworten Zitat
Benutzerbild von sundance
sundance

Registriert seit: 9. Mai 2006
98 Beiträge
 
Delphi 7 Professional
 
#8

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 5. Dez 2013, 08:35
@Frank:
Gute Idee. Hier liegt die Datenbank allerdings gegeben vor, also muss ich mit "index" vorlieb nehmen... Aber beim nächsten Datenbankprojekt soll's dann besser werden.

@Stephan:
OK, "kompliziert" war nicht der richtige Ausdruck.
Was ich meinte war, dass die zeilenweise Zuordnung von Feld und Wert übersichtlicher ist als ein langer SQL-String. Aber das mit "ParameterByName" sieht interessant aus. Werde ich gleich mal probieren.

Ach ja, noch was:
Wie kann man sicher überprüfen, ob nach einem uniConn.Open bzw. uniConn.ExecSQL die jeweiligen Aktionen fehlerfrei verlaufen sind? Gibt es da bei UniDAC eine Statusabfrage oder wird im Fehlerfall eine Exception ausgelöst?

Vielen Dank für eure Unterstützung
sundance

Geändert von sundance ( 5. Dez 2013 um 08:43 Uhr)
  Mit Zitat antworten Zitat
schlecki

Registriert seit: 11. Apr 2005
Ort: Darmstadt
148 Beiträge
 
Delphi XE2 Enterprise
 
#9

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 5. Dez 2013, 09:21
Hi,

ein weiterer Vorteil von ParamByName ist, dass man sich um Quotes und die Konvertierung des Datentyps keine Gedanken machen muss.
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#10

AW: UniDac Select & Edit (Anfängerfrage)

  Alt 5. Dez 2013, 09:24
Aus diesem Grund habe ich mir bereits vor langer Zeit angewöhnt, die Index-Spalte einer Tabelle stets mit dem Tabellen-Namen zu verbinden, z.B. Idx_Adressen, Idx_Kategorie usw. Nach Möglichkeit sollte man Tabellen- und Spaltennamen mit aussagekräftigen Bezeichnern versehen, um die Lesbarkeit erhöhen. Hat man sich erst einmal an ein bestimmtes Schema gewöhnt, entfällt oft auch das Nachschlagen bzw. Suchen eines Spalten- oder Tabellennamens, denn der ergibt sich dann oft von selbst. Ich weiß also, daß z.B. meine Index-Spalten immer mit Idx_ beginnen und kann so viel flüssiger arbeiten.
Diesen Tip halte ich für fragwürdig. Ein Index ist ein "physikalische" Möglichkeit, den Zugriff auf einen Datensatz über bestimmter Felder zu beschleunigen. Welche Felder einen solchen Index besitzen und welche vielleicht einen gemeinsamen Index haben, sollte mit dem Datenmodell und der Benennung nichts zu tun haben.
Wie würdest Du z.B. ein Feld nennen, dass Teil eines Index ist?
Offensichtlich wird gern der Unterschied zwischen Index und Key Constraint vernachlässigt, beides existiert aber technisch völlig unabhängig voneinander und kann auch so eingesetzt werden.

D.h. es ist möglich, eine Primärschlüsselspalte ohne Index zu verwenden (macht natürlich wenig Sinn). Es ist auch möglich einen Index anzulegen, der zu keinem Key Konstraint bzw. logischen Fremdschlüssel gehört. Das macht je nach Anwendungsfall schon sehr viel Sinn und ergibt sich u.U. erst in einer späteren Lebensphase der Datenbank (Tuning).

Feldnamen sollten primär an der Logik des Datenmodells und am Feldinhalt orientiert sein, nicht an physikalischen Gegebenheiten. Die ändern sich nämlich gern mal und dann kann man mit seinen "Konventionen" ganz schön auf dem Bauch landen.
Jedes RDBMS trennt physikalische Optionen (z.B. in der Create Table Anweisung) von den logischen Optionen.
Gruß, Jo
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 17:10 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