Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Quellcode mal bitte angucken (https://www.delphipraxis.net/39074-quellcode-mal-bitte-angucken.html)

Luckie 28. Jan 2005 09:17


Quellcode mal bitte angucken
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, ich habe mir innerhalb eines knapp zweitägigen Crashkurses mehr oder weniger die Grundlagen von (my)SQL angeeignet. Das heißt, ich kann eine Datenbank erstellen, eine einfache Tabelle anlegen und mit dieser Tabelle die gängigen Datenbankoperationen ausführen: Einfügen, ändern, löschen, sortieren.

Das habe ich an Hand von Chewies Tutorial gemacht, bis zur zweiten Seite habe ich gelesen oder so und dieser Seite, der Rest war "learning by doing". (Als Programmierer kann man sich das ja leisten, als Chirug nicht unbedingt. :mrgreen:) Dabei rausgesprungen ist eine kleine Adress-Datenbank.

Ich würde, die jenigen von euch, die sich etwas mit SQL und speziell mySQL auskennen, jetzt mal bitten über den Code drüber zugucken, ob das so in Ordnung ist, also das Datenbank technische.

Die Datenbank benötigt den mySQL-Server.
Bevor ihr Daten eingeben könnt, müsst ihr eine Datenbank erstellen und dann die Tabelle. Die Schaltfläche "Import" läd eine csv Datei mit dem Namen "Adressen.csv" und dem Aufbau: "Namne, Vorname, Strasse, PLZ, Ort, Telefon, Handy, EMail". Das war nur für mich, um aus meiner Adressedatenbank da ein paar Datensätze reinzubekommen. Sortieren kann man die Datenbank, in dem man in das Texteingabefeld die zu sortierenden Spalten mit einem Komma getrennt eingibt und dann auf "Sortieren" klick. (Wäre bestimmt auch per Klick auf einen Spaltenkopf gegangen, aber darauf kam es mir nicht an.)

Also mich interessiert, was ihr von dem Code haltet, das Design, die Funktionalität und die Bedienbarkeit der GUI spielen keine Rolle.

Könnte man somit, nach diesem Projekt, sagen, dass ich die nötigsten Grundlagen beherrsche?

Chewie 28. Jan 2005 10:09

Re: Quellcode mal bitte angucken
 
Ich würds mir ja gerne ankucken, hab aber leider keinen funktionierenden Rechner zu Hause. Vielleicht aber am Wochenende...
Wenns klappt, schau ich mal durch.

Luckie 28. Jan 2005 10:31

Re: Quellcode mal bitte angucken
 
Den Code kannst du doch auch im Notepad öffnen. Und mit irgendwas Rechner ähnlichen musst du ja dieses Posting erstellt haben ;)

Jelly 28. Jan 2005 10:46

Re: Quellcode mal bitte angucken
 
Hallo Luckie,

ich kann leider keine Datenbank anlegen, obwohl ich die Konstanten (Host etc) richtig gesetzt hab. Vielleicht hast du/ich ein Verständnisproblem, was der Unterschied zwischen Datenbank und Tabelle ist...

du hast ein konstante _DB: Die interpretier ich als Name der Datenbank
und eine Konstante DBNAME: Das interpretier ich als der Name der Tabelle. Das kann dann aber nicht so ganz sein, da du z.B. in der Insert-Methode in die Tabelle Kontakte schreibst...

Auf deutsch: ich versteh den Unterschied von _DB und DBNAME nicht?

Luckie 28. Jan 2005 10:52

Re: Quellcode mal bitte angucken
 
Ja, das sind noch Überbleipsel aus dem gewachsenen Code. Ich hatte anfangs erstmal nur Versucht eine Verbindung zum DB-Server zu bekommen, dort habe ich _DB benutzt:

Delphi-Quellcode:
procedure Connect(var ConDes: PMYSQL; const Host, User, PW, DB: string; Port:
  Integer);
begin
  if Assigned(ConDes) then
  begin
    log('Verbindungsdeskriptor initialisiert');
    if Assigned(mysql_real_connect(ConDes, PChar(Host), PChar(User), PChar(PW),
      PChar(DB), PORT, nil, 0)) then
    begin
      log('Verbindung zum Datenbankserver hergestellt');
    end
    else
      log(mysql_error(ConDes));
  end
  else
    log('Initialisierung fehlgeschlagen');
end;
Aufruf:
Delphi-Quellcode:
Connect(Descriptor, _HOST, _USER, _PW, _DB, _PORT);
Beim Anlegen der Datenbank habe ich dann DBNAME genommen:
Delphi-Quellcode:
procedure TForm1.btnCreateBDClick(Sender: TObject);
var
  query       : PChar;
  ErrorCode   : Integer;
begin
  query := 'CREATE DATABASE' + ' ' + DBNAME;
  try
    ErrorCode := mysql_real_query(ConDes, query, length(query));
    if ErrorCode = 0 then
      log('Datenbank angelegt')
    else
      log(mysql_error(Descriptor));
  except
    log('EXCEPTION Datenbank konnte nicht angelegt werden');
  end;
end;
Und selbige Konstante dann weiter benutzt. Ist etwas blöd, stimmt.

Jelly 28. Jan 2005 10:54

Re: Quellcode mal bitte angucken
 
Habs jetzt ne Datenbank erstellt gekriegt, der Unterschied zwischdn _DB und DBNAME weiss ich aber immer noch nicht..

Zu deiner Datenbank selbst: du nutzt überall den Feldtyp Text. Das macht die Datenbank nicht gerade effizient, auch wenns bei paar Adressen egal ist. Text ist ein sogenanntes Blob-Feld, und vergleichbar mit einem Memo. Da kannst du beliebig viel reinschreiben, hat aber auch gravierende Nachteile:

1) in den meisten Datenbanksystemen ist über Blob-Felder kein Suchen möglich, auch wenn bei MySQL funzt
2) du kannst über Blob-Felder keine Indizes rsp Schlüssel legen. Dadurch wird das Sortieren und deine Joins zwischen Tabellen sehr langsam, da alles sequentiell durchgescannt werden muss.

Nimm also, bei Felder wie name, vorname lieber den Typ varchar, und leg dort eine maximale Länge fest.

Den Typ Text kannst du z.B. verwenden, wenn du noch einen Kommentar zu einer Adresse aufnehmen willst.

Luckie 28. Jan 2005 11:01

Re: Quellcode mal bitte angucken
 
Es gibt keinen. Lösch die Konstante _DB aus dem Quellcode und gib dort, wo sie verlangt wird, einen Leerstring an.

Danke für den Tipp.

Nightshade 28. Jan 2005 12:40

Re: Quellcode mal bitte angucken
 
Ich bekomme eine AV (im Modul libmysql.dll) beim Drücken von "DB Anlegen".

Habe die DB dann von Hand angelegt, dann ging alles.
Sieht ganz gut aus.

Evt. als Vorschlag für dich, zu dem Projekt passt ganz gut der embedded MySQL-Server.

Chewie 28. Jan 2005 16:24

Re: Quellcode mal bitte angucken
 
So, ich sitz jetzt endlich wieder an meinem Rechner :)

Dein Code ist soweit OK, außer dass du für die Fehlerabfragen, wie ich schon in irgendeinem Thread erwähnt habe, mysql_error benutzen kannst. Bei Schreibe-Queryes ist vielleicht noch mysql_affected_rows ganz interessant.

Luckie 28. Jan 2005 16:25

Re: Quellcode mal bitte angucken
 
Zitat:

Zitat von Nightshade
Ich bekomme eine AV (im Modul libmysql.dll) beim Drücken von "DB Anlegen".

Sollte eigentlich nicht. :gruebel:

Sharky 29. Jan 2005 07:06

Re: Quellcode mal bitte angucken
 
Zitat:

Zitat von Nightshade
Ich bekomme eine AV (im Modul libmysql.dll) beim Drücken von "DB Anlegen"....

Kopiere mal die libmySQL.dll von deinem mySQL-Server in das Verzeichniss von Luckies Anwendung.

[Edit]Uff... bei mir passier ja das selbe. Muss ich mir mal ansehen

Sharky 29. Jan 2005 07:37

Re: Quellcode mal bitte angucken
 
Zitat:

Zitat von Luckie
... was ihr von dem Code haltet, ...

Ein kleiner Tip am Rande ;-)
Die PLZ als Integer zu speichern ist zwar effektiv. Aber (es gibt ja immer ein aber). Wenn ich eine Postleitzahl eingebe die mir 0 beginnt stimmt natürlich die Anzeige nicht mehr und auch das Suchen würde nicht sauber funktionieren. Darum würde ich da lieber ein VarChar(5) verwenden.

runger 29. Jan 2005 07:52

Re: Quellcode mal bitte angucken
 
Hallo sharky,

erklär mal bitte für alle Ahnungslosen was ein varchar(5) ist.

Rainer

Sharky 29. Jan 2005 08:00

Re: Quellcode mal bitte angucken
 
Zitat:

Zitat von runger
...erklär mal bitte für alle Ahnungslosen was ein varchar(5) ist...

Hai Rainer,
das ist ein Datenbankfeld das bis zu 5 Zeichen Text auf nehmen kann.

runger 29. Jan 2005 08:02

Re: Quellcode mal bitte angucken
 
Danke,

hab ich nicht gewusst.

Rainer

Sharky 29. Jan 2005 08:12

Re: Quellcode mal bitte angucken
 
Zitat:

Zitat von Luckie
... was ihr von dem Code haltet, ...

Hai Luckie,
noch zwei Anmerkungen :stupid:
a)
Warum stellst Du die Verbindung zu mySQL-Server im OnPaint deiner Form her? Wäre es nicht besser das einmalig im OnCreate zu machen.

b)
Du verwendest eine Spalte deiner StringGrid zum "speichern" der ID jeder Adresse. Ich habe mir angewöhnt dafür die Eigenschaft Obejects zu missbrauchen. Diese hast Du dann nämlich auch bei TListBoxen TListViews und allem was ein TStrings Property hat.
Im OnSelectCell deines StringGrids müsstest Du das so änder:
Delphi-Quellcode:
  ID := Integer(StringGrid1.Objects[0,ARow]);
//  ID := StrToIntDef(StringGrid1.Cells[0, ARow], 0);
und in deinem FillStringGrid noch das:
Delphi-Quellcode:
    StringGrid1.Objects[0,i+1] := TObject (Kontakte[i].ID);
//    StringGrid1.Cells[0, i + 1] := IntToStr(Kontakte[i].ID);

Luckie 29. Jan 2005 09:50

Re: Quellcode mal bitte angucken
 
Zitat:

Zitat von Sharky
Warum stellst Du die Verbindung zu mySQL-Server im OnPaint deiner Form her? Wäre es nicht besser das einmalig im OnCreate zu machen.

Weil es cooler aussieht, wenn die Form schon sichtbar ist und dann erst das StringGrid gefüllt wird. Nein, ich wollte zum Debuggen de Meldungen im Memo sehen. Und außerdem wird die Verbindung ja auch nur einmal hergestellt.

Zitat:

Du verwendest eine Spalte deiner StringGrid zum "speichern" der ID jeder Adresse.
Nun ja. Das muss ich sowie so noch mal umbauen und alles dynamisch machen. Sprich die Anzahl der Spalten usw. und dabei werden wohl alle Felder der DB zu varchar Feldern werden. Ich dachte mir dann sowas:
Delphi-Quellcode:
type
  TKonatkte = array of String;
  TCols = array of String;

GetKontakte(var Kontakte: TKonatkte; var Cols: TCols);

FillStringGrid(SG: TStringGrid, Kontakte: TKontakte, Cols: TCols);
begin
  SG.Cols := length(Ciols);
  for i := 0 to length(Cols) - 1 do
  begin
    SG.Cells[0, i] := Cols[i];
  end;
  SG.Rows := length(Kontakte);
  for i := 0 to length(Kontakte) - 1 do
  begin
    ....;
    ....;
  end;
end;
Dann kann man das für jede beliebige Datenbank einsetzten.

Denn wenn ich jetzt so was mache:
SQL-Code:
SELECT name, vorname FROM kontakte
dann stürzt mit alles ab. Da muss ich noch eine universelle Lösung finden

Luckie 29. Jan 2005 14:51

Re: Quellcode mal bitte angucken
 
So, hier du Umsetzung:
Delphi-Quellcode:
type
  TRows = array of array of string; // [Cols, Rows]
  TCols = array of string;

function ExecQuery(const query: string; var Cols: TCols; var Rows: TRows):
  Boolean;
var
  MySQLRes    : PMYSQL_RES;
  MySQLRow    : PMYSQL_ROW;
  AffectedRows : Int64;
  ColCount    : Cardinal;
  Field       : PMYSQL_FIELD;
  i           : Integer;
  j           : Integer;
  ErrorCode   : Integer;
begin
  ErrorCode := mysql_select_db(Descriptor, DBNAME);
  if ErrorCode = 0 then
  begin
    ErrorCode := mysql_real_query(Descriptor, PChar(query), length(query));
    if ErrorCode = 0 then
    begin
      MySQLRes := mysql_store_result(Descriptor);
      if Assigned(MySQLRes) then
      begin
        ColCount := mysql_num_fields(MySQLRes);
        SetLength(Cols, ColCount);
        for i := 0 to ColCount - 1 do
        begin
          Field := mysql_fetch_field_direct(MySQLRes, i);
          Cols[i] := Field.Name;
        end;
        AffectedRows := mysql_affected_rows(Descriptor);
        SetLength(Rows, ColCount, AffectedRows);
        for i := 0 to ColCount - 1 do
        begin
          for j := 0 to AffectedRows - 1 do
          begin
            MySQLRow := mysql_fetch_row(MySQLRes);
            Rows[i, j] := MySQLRow[i];
          end;
          mysql_real_query(Descriptor, PChar(query), length(query));
          MySQLRes := mysql_store_result(Descriptor);
        end;
        log(Format('Betroffene Zeile: %d', [mysql_affected_rows(Descriptor)]));
        mysql_free_result(MySQLRes);
      end
    end
  end;
  result := ErrorCode = 0;
end;

procedure FillGrid(SG: TStringGrid; Cols: TCols; Rows: TRows);
var
  i, j        : Integer;
begin
  SG.ColCount := 0;
  SG.RowCount := 0;
  if Assigned(Rows) then
  begin
    SG.RowCount := length(Rows[0]);
    SG.ColCount := length(Cols);
    SG.FixedRows := 1;
    for i := 0 to length(Cols) - 1 do
    begin
      SG.Cols[i].Add(Cols[i]);
      SG.Cells[i, 0] := Cols[i];
    end;
    for i := 0 to length(Cols) - 1 do
    begin
      for j := 0 to length(Rows[0]) - 1 do
      begin
        SG.Cells[i, j + 1] := Rows[i, j];
      end;
    end;
  end;
end;
Und ein Aufruf könnte so aussehen:
Delphi-Quellcode:
if ExecQuery(query, Cols, Rows) then
  FillGrid(StringGrid1, Cols, Rows)

Luckie 29. Jan 2005 16:02

Re: Quellcode mal bitte angucken
 
375 Aufrufe! :shock: Liegt das jetzt an mir oder an dem Thema? :gruebel:

Generalissimo 29. Jan 2005 16:12

Re: Quellcode mal bitte angucken
 
Zitat:

Zitat von runger
Hallo sharky,

erklär mal bitte für alle Ahnungslosen was ein varchar(5) ist.

Rainer

Genauer ein Textfeld mit variabler Länge bis 5. Werden hier nur 3 Textzeichen eingegeben werden auch nur für 3 Zeichen Speicher benutzt. Char(5) bedeutet das immer für 5 Zeichen Speicher besetzt wird.

Robert_G 29. Jan 2005 16:28

Re: Quellcode mal bitte angucken
 
Wenn ich ehrlich sein darf: Mir gefällt der Code Style gar nicht. :duck:
Klassenlose Funktionen, globale Variablen, Records, Arrays,... alles Dinge die ich persönlich eher als Quick&Dirty bezeichnen würde. :angle2:


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:15 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