AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Zugriff auf MySQL ohne Komponenten mit Delphi XE2
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriff auf MySQL ohne Komponenten mit Delphi XE2

Ein Thema von Ykcim · begonnen am 1. Okt 2011 · letzter Beitrag vom 18. Okt 2011
Antwort Antwort
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#1

Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 1. Okt 2011, 21:26
Datenbank: MySQL • Version: 5 • Zugriff über: mysql.pas
Hallo Zusammen,

ich habe bislang auf den MySQL ohne Komponenten zugegriffen, mit dem nachfolgenden Code:

Delphi-Quellcode:
procedure connect;
var Datei: TextFile;
    MyString: String;
begin
  AssignFile(Datei, ExtractFilePath(Application.ExeName) + 'SQL.set');
  Reset(Datei);
  try
    ReadLn(Datei, MyString);
    host := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
    ReadLn(Datei, MyString);
    User := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
    ReadLn(Datei, MyString);
    Pass := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
    ReadLn(Datei, MyString);
    DB := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
  finally
    CloseFile(Datei);
  end;
  _myCon := mysql_init(nil);
  if _mycon=nil then
  begin
    showmessage('Nicht genügend freier Speicher!');
    Exit;
  end;
  if mysql_real_connect(_mycon, host, user, pass,db, 3306, nil,0)=nil then
  begin
    showmessage('Die Verbindung konnte nicht hergestellt werden! Ursache:' + mysql_error(_mycon));
    exit;
  end;
end;
Das funktionierte auch wunderbar und zuverlässig. Jetzt versuche ich gerade den Umstieg von TurboDelphi auf Delphi xe2 starter. Und das ist das Problem. Ich bekomme keine Verbindung mehr zu der Datenbank.

An dieser Stelle im Code macht er einen Fehler:
_myCon := mysql_init(nil);
Hat jemand eine Idee, woran das liegen kann? Die Datenbank hat sich nicht geändert, es muss mit Delphi xe2 zusammenhängen.

Vielen Dank
Ykcim
Patrick
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 1. Okt 2011, 21:47
Zitat:
An dieser Stelle im Code macht er einen Fehler:
Welcher?
Markus Kinzler
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 1. Okt 2011, 21:51
Delphi-Quellcode:
procedure connect;
var Datei: TextFile;
     MyString: String;
begin
   AssignFile(Datei, ExtractFilePath(Application.ExeName) + 'SQL.set');
   Reset(Datei);
   try
     ReadLn(Datei, MyString);
     host := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
     ReadLn(Datei, MyString);
     User := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
     ReadLn(Datei, MyString);
     Pass := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
     ReadLn(Datei, MyString);
     DB := Pchar(copy(MyString, pos(':', MyString)+1, length(MyString)));
   finally
     CloseFile(Datei);
   end;

  //AN DIESER STELLE
   _myCon := mysql_init(nil);


   if _mycon=nil then
   begin
     showmessage('Nicht genügend freier Speicher!');
     Exit;
   end;
   if mysql_real_connect(_mycon, host, user, pass,db, 3306, nil,0)=nil then
   begin
     showmessage('Die Verbindung konnte nicht hergestellt werden! Ursache:' + mysql_error(_mycon));
     exit;
   end;
end;

Ich bekomme einfach nur eine Meldung, dass die Verbindung nicht hergestellt werden kann...
Patrick
  Mit Zitat antworten Zitat
Benutzerbild von geskill
geskill

Registriert seit: 17. Feb 2007
Ort: NRW
420 Beiträge
 
Delphi 2010 Professional
 
#4

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 1. Okt 2011, 22:03
Sieht wie ein Unicode/Ansi Problem aus. TurboDelphi benutzt ja standardmäßig AnsiString.

Delphi-Quellcode:
procedure connect;
var Datei: TextFile;
      MyString: Ansistring;
begin
    AssignFile(Datei, ExtractFilePath(Application.ExeName) + 'SQL.set');
    Reset(Datei);
    try
      ReadLn(Datei, MyString);
      host := PAnsiChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
      ReadLn(Datei, MyString);
      User := PAnsiChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
      ReadLn(Datei, MyString);
      Pass := PAnsiChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
      ReadLn(Datei, MyString);
      DB := PAnsiChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
    finally
      CloseFile(Datei);
    end;

    //...

EDIT:
Quatsch der Fehler kommt ja schon vorher. Denke mal du hast dann die neue mysql.pas (Version 2011-09-15)
für XE2. Im Header steht da folgendes:

Zitat:
procedure mysql_server_end;
{ "Jeremiah Gowdy" <jgowdycox.net> wrote on 10/11/2005 03:08:40 AM:
The Windows DLL is thread safe. You do not have to call my_init()
and my_thread_init() because Windows DLLs receive events when they
are attached to a new process and when they are attached to a new
thread in a process. This is one of the nicer features of Windows
shared libraries. Other than that, you don't have to do anything
special. I am a heavy user of libmysql under Win32. You simply
mysql_init() your MYSQL struct, and then mysql_real_connect() and
you're ready to mysql_query().
New on February 17, 2009 02:27AM: This is true until 5.0.77 -
since this version this nice feature ist removed from dll.c.
To obtain the previous behavior (DLL initialization code will be
called), set the LIBMYSQL_DLLINIT environment variable to
any value. http://forums.mysql.com/read.php?3,248207,248207 }
function mysql_thread_init: my_bool; //called internal by mysql_init or mysql_server_init
{ New on February 17, 2009 02:27AM: Since 5.0.77 mysql_thread_end
is not called during DllMain() if the LIBMYSQL_DLLINIT environment variable is
not set. So it is necessary to call mysql_thread_end to avoid memory leaks. }
procedure mysql_thread_end;
Aber das wäre ja nur der Fall für Threadsicherheit.

Aber du hast ja nicht die Unit von TurboDelphi für XE2 benutzt, weil da brauchst du denke ich
die neue welche extra dafür kompatibel gemacht wurde.
Sebastian

Geändert von geskill ( 1. Okt 2011 um 22:18 Uhr)
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 1. Okt 2011, 22:23
Vielen Dank für die Antwort!

Ich habe den Code jetzt soweit geändert:

Delphi-Quellcode:
var
  Form1: TForm1;
  _myCon: PMYSQL;
  host, user, pass, db: PChar;
  ErrorCode: Integer;
  MySQLRes: PMYSQL_RES;
  MySQLRow: PMYSQL_ROW;
  AffectedRows: Int64;
  Field: PMYSQL_FIELD;

//...

procedure connect;
var Datei: TextFile;
       MyString: Ansistring;
begin
     AssignFile(Datei, ExtractFilePath(Application.ExeName) + 'SQL.set');
     Reset(Datei);
     try
       ReadLn(Datei, MyString);
       host := PChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
       ReadLn(Datei, MyString);
       User := PChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
       ReadLn(Datei, MyString);
       Pass := PChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
       ReadLn(Datei, MyString);
       DB := PChar(copy(MyString, pos(':', MyString)+1, length(MyString)));
     finally
       CloseFile(Datei);
     end;
  end;
{73}  _myCon := mysql_init(nil);
  if _mycon=nil then
  begin
    showmessage('Nicht genügend freier Speicher!');
{78}    Exit;
  end;
{80}  if mysql_real_connect(_mycon, host, user, pass,db, 3306, nil,0)=nil then
  begin
    showmessage('Die Verbindung konnte nicht hergestellt werden! Ursache:' + mysql_error(_mycon));
    exit;
{83}  end;
end;

Leider habe ich es jetzt noch nicht geschafft, wieder zu kompilieren, da ich diverse Fehler bekomme:
Zitat:
[DCC Fehler] Unit1.pas(73): E2029 Deklaration erwartet, aber Bezeichner '_myCon' gefunden
[DCC Fehler] Unit1.pas(78): E2029 '.' erwartet, aber ';' gefunden
[DCC Fehler] Unit1.pas(80): E2004 Bezeichner redefiniert: 'Finalization'
[DCC Warnung] Unit1.pas(83): W1011 Text hinter dem abschließenden 'END.' - wird vom Compiler ignoriert
[DCC Fehler] Unit1.pas(13): E2065 Ungenügende Forward- oder External-Deklaration: 'TForm1.Button1Click'
[DCC Fataler Fehler] Project1.dpr(5): F2063 Verwendete Unit 'Unit1.pas' kann nicht compiliert werden
Misslungen
Verstrichene Zeit: 00:00:00.2
Könnt Ihr mir sagen, wo diese Fehler liegen?

Vielen Dank
Ykcim
Patrick
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 1. Okt 2011, 22:45
Vergesst das!

Ich habe mir die neuste mysql.pas heruntergeldaen, aber da bekomme ich Kompilierungsfehler...

Versuche es nachzuvollziehen.
Patrick
  Mit Zitat antworten Zitat
wurzelzwerg

Registriert seit: 19. Jun 2011
Ort: Ilmenau
111 Beiträge
 
Delphi XE5 Enterprise
 
#7

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 2. Okt 2011, 09:49
Vor {73} ist ein end zu viel.
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#8

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 2. Okt 2011, 11:31
Die mysql-Funktionen arbeiten intern mit AnsiStrings bzw. UFT8Strings.
host, user, pass, db: PChar; deklariert aber Unicode-Strings.

Delphi-Quellcode:
var
   Form1: TForm1;
   _myCon: PMYSQL;
   host, user, pass, db: AnsiString;
   ErrorCode: Integer;
   MySQLRes: PMYSQL_RES;
   MySQLRow: PMYSQL_ROW;
   AffectedRows: Int64;
   Field: PMYSQL_FIELD;

//...

procedure connect;
var Datei: TextFile;
        MyString: Ansistring;
begin
    AssignFile(Datei, ExtractFilePath(Application.ExeName) + 'SQL.set');
    Reset(Datei);
    try
      ReadLn(Datei, MyString);
      host := copy(MyString, pos(':', MyString)+1, MaxInt);
      ReadLn(Datei, MyString);
      User := copy(MyString, pos(':', MyString)+1, MaxInt);
      ReadLn(Datei, MyString);
      Pass := copy(MyString, pos(':', MyString)+1, MaxInt);
      ReadLn(Datei, MyString);
      DB := copy(MyString, pos(':', MyString)+1, MaxInt);
    finally
      CloseFile(Datei);
    end;
   _myCon := mysql_init(nil);
   if _mycon=nil then
   begin
     showmessage('MySql-Verbindung konnte nicht initialisiert werden!');
     Exit;
   end;
  if mysql_real_connect(_mycon, PAnsiChar(host), PAnsiChar(user), PAnsiChar(pass),PAnsiChar(db), 3306, nil,0)=nil then
   begin
     showmessage('Die Verbindung konnte nicht hergestellt werden! Ursache:' + mysql_error(_mycon));
     exit;
  end;
end;
Tip 1: Seit einigen Jahren lädt die mysql.pas die DLL nicht mehr automatisch (per Compilerschalter kann dieses Verhalten jedoch geändert werden). Statt dessen sollte die DLL per libmysql_fast_load(nil) geladen werden.
Tip 2: Da der interne Aufbau des Records TMYSQL_FIELD von der verwendeten Version der LibMySql.dll abhängt, sollte man den direkten Zugriff auf dieses Record vermeiden und stattdessen die Funktionen "mysql_field_type", "mysql_field_flag", "mysql_field_length", "mysql_field_name", "mysql_field_tablename", "mysql_field_default" usw. benutzen. Diese Funktionen erlauben einen Zugriff auf die Feldparameter unabhängig von der beim Benutzer/Kunden installierten Version der LibMySql.dll.

Geändert von samso ( 2. Okt 2011 um 13:43 Uhr) Grund: length(MyString) ist unsinnig
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 18. Okt 2011, 10:42
Hallo Zusammen,

ich bin leider noch nicht wirklich weitergekommen mit meinen Bemühungen, mit Delphi xe2 starter auf eine MySQL-Datenbank zugreifen zu können.
Das ganze soll ohne Komponenten möglich sein.
Vielleicht hat jemand das Thema schon gelöst - ich habe aber noch nichts gefunden...
Angedacht sind drei Prozeduren/Funktionen: Connect, ExecQuery und disconnect.
Nachstehend was ich bis hierhin gefrickelt habe, in der Hoffnung, dass wir es hier dann zum Laufen bringen...

KOPF:
Delphi-Quellcode:
unit DBconnectUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids,
  Vcl.StdCtrls, mysql;

type
  TForm1 = class(TForm)
    Button1: TButton;
    StringGrid1: TStringGrid;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

type
  TRows = array of array of string; // [Cols, Rows]
  TCols = array of string;

var
  Form1: TForm1;
  LibHandle: PMYSQL;
  mySQL_Res: PMYSQL_RES;
  ErrorCode: Integer;
  ColCount: integer;
  AffectedRows: Int64;
  host, User, Pass, DB: Ansistring;

implementation

{$R *.dfm}


CONNECT:
Delphi-Quellcode:
procedure connect;
var
  MYSQL_ROW: PMYSQL_ROW;
  Datei: TextFile;
  MyString: String;
begin
  libmysql_fast_load(nil);
  AssignFile(Datei, ExtractFilePath(Application.ExeName) + 'SQL.set');
  Reset(Datei);
  try
    ReadLn(Datei, MyString);
    host := copy(MyString, pos(':', MyString)+1, length(MyString));
    ReadLn(Datei, MyString);
    User := copy(MyString, pos(':', MyString)+1, length(MyString));
    ReadLn(Datei, MyString);
    Pass := copy(MyString, pos(':', MyString)+1, length(MyString));
    ReadLn(Datei, MyString);
    DB := copy(MyString, pos(':', MyString)+1, length(MyString));
  finally
    CloseFile(Datei);
  end;
  if mySQL_Res<>nil
  then
    mysql_free_result(mySQL_Res);
  mySQL_Res := nil;
  if LibHandle<>nil
  then begin
    mysql_close(LibHandle);
    LibHandle := nil;
  end;
  LibHandle := mysql_init(nil);
  if LibHandle=nil
  then
    raise Exception.Create('mysql_init failed');
  if (mysql_real_connect(LibHandle,
                         PAnsiChar(AnsiString(Host)),
                         PAnsiChar(AnsiString(User)),
                         PAnsiChar(AnsiString(Pass)),
                         PAnsiChar(AnsiString(DB)),
                         3306, nil, 0)=nil)
  then
    raise Exception.Create(mysql_error(LibHandle));
end;


EXECQUERY:
Delphi-Quellcode:
function ExecQuery(const Datenbank, query: string; var Cols: TCols;
                   var Rows: TRows): Boolean;
var
  j, i, field_count, row_count: Integer;
  mySQL_Field: PMYSQL_FIELD;
  tablename: String;
  MYSQL_ROW: PMYSQL_ROW;
begin
   SetLength(Cols, 0);
   // Datenbank auswählen
   ErrorCode := mysql_select_db(LibHandle, PAnsiChar(AnsiString(Datenbank)));
   if ErrorCode = 0 then
   begin
     // Query ausführen
   if mysql_real_query(LibHandle, PAnsiChar(query), Length(query))<>0
    then begin
      raise Exception.Create(mysql_error(LibHandle));
      exit;
     end
     else
     begin
       // Query speichern
       mySQL_Res := mysql_store_result(LibHandle);
       if mySQL_Res<>nil
       then begin
         // zurückgelieferte Anzahl der Spalten
         ColCount := mysql_num_fields(mySQL_Res);
         SetLength(Cols, ColCount);
         SetLength(Rows, ColCount, 0);
         SetLength(Cols, ColCount);
         // Spalten-Array füllen
         for i := 0 to ColCount - 1 do
         begin
           mySQL_Field := mysql_fetch_field_direct(mySQL_Res, i);
           Cols[i] := mysql_field_name(mySQL_Field);
         end;
         // Anzahl der betroffenen Zeilen ermitteln
         AffectedRows := mysql_num_rows(mySQL_Res);
         SetLength(Rows, ColCount, AffectedRows);
         // neu ->
         // Zeilen-array füllen
         // alle Zeilen ...
         for j := 0 to AffectedRows - 1 do
         begin
           // ... werden eingelesen
           MySQL_Row := mysql_fetch_row(mySQL_Res);
           // alle Spalten ...
           for i := 0 to ColCount - 1 do
           begin
             // ... werden in Rows[] übertragen
             Rows[i, j] := MySQL_Row[i];

           end;
         end;
         // gespeicherte Abfrage wieder freigeben
         mysql_free_result(MySQL_Res);
       end
     end
   end;
   result := ErrorCode = 0;
end;


DISCONNECT:
Delphi-Quellcode:
procedure disconnect;
begin
  mysql_close(LibHandle);
  LibHandle := nil;
  if mySQL_Res<>nil
  then
    mysql_free_result(mySQL_Res);
  if libmysql_status=LIBMYSQL_READY
  then
    mysql_close(LibHandle);
  libmysql_free;
end;


AUFRUF:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  query: Ansistring;
  Cols: TCols;
  Rows: TRows;
begin
  query:='select * from as400';
  connect;
  ExecQuery(db, query, Cols, Rows);
  disconnect;
  FillGrid(StringGrid1, Cols, Rows);
end;

Im Moment passiert Folgendes:
Beim ausführen bekomme ich eine Fehlermeldung, dass ich einen Fehler in meinem SQL-Syntax hätte. Das ist nicht der Fall, denn wenn ich den Wert aus der Variablen "query" in dem MySQL-Server direkt ausführe funktioniert es...

Der Fehler wird in der MySQL.pas erzeugt, in dieser Prozedure:
Delphi-Quellcode:
function mysql_error(_mysql: PMYSQL): PAnsiChar;
begin
  if @_mysql_error=nil
  then
    LoadProcAddress(@_mysql_error, 'mysql_error');
  Result := _mysql_error(_mysql);
end;

Die Fehlermeldung lautet:
Zugriffsverletzung bei FFFEB4E8 und Zugriff auf FFFEB4E8

Delphi-Übersetzung:
Im Projekt DBconnect ist eine Exception der Klasse Exception mit der Meldung 'You have an error in your MySQL-Syntax; check manual ...


Ich bewege mich mit dieser Sache auf zu dünnem Eis und bin auf Hilfe angewiesen. Kann mir jemand helfen, wie ich auf diese Weise die Verbindung zu meinem MySQL-Server hinbekomme?

Vielen Dank im Voraus

Ykcim
Patrick
  Mit Zitat antworten Zitat
Ykcim

Registriert seit: 29. Dez 2006
Ort: NRW
804 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Zugriff auf MySQL ohne Komponenten mit Delphi XE2

  Alt 18. Okt 2011, 15:14
Hallo Zusammen,

den genannten Fehler konnte ich beheben: Ich musste die Variable query und Datenbank von string auf AnsiString ändern.

Delphi-Quellcode:
function ExecQuery(const Datenbank, query: Ansistring; var Cols: TCols;
                   var Rows: TRows): Boolean;

Die Procedure disconnect ist wie folgt angepasst, aber da glaube ich, dass noch nicht alles rund läuft. Kommentare dazu sind willkommen.

Delphi-Quellcode:
procedure disconnect;
begin
  mysql_close(LibHandle);
  LibHandle := nil;
  mySQL_Res := nil;
  libmysql_free;
end;

Ykcim
Patrick
  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 01:04 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