function FindUserWithId1 : String;
var
FMySQL : PMYSQL;
FMyTime : longword;
Session : PMYSQL;
Res : PMYSQL_RES;
Row : PMYSQL_ROW;
RowCount : int64;
Query : String;
begin
Result := ''; // default returnere vi en tom streng.
FMyTime := 30; // sæt 30 sekunders timeout.
FMySQL := mysql_init(nil); // initalisere en MySQL session.
mysql_options(FMySQL, MYSQL_OPT_CONNECT_TIMEOUT, @FMyTime); // sæt 30 sekunders timeout
Session := mysql_real_connect(FMySQL, 'Host', 'User', 'Password', 'Database', 0, nil, 0);
if (Session <> nil) then
begin // Vi har forbindelse til databasen.
Query := 'SELECT name FROM Users WHERE id=1';
if mysql_real_query(FMySQL, PChar(Query), length(Query)) = 0 then
begin // Vores forspørgelse gik godt.
Res := mysql_store_result(FMySQL); // Hent resultat sættet fra MySql.
RowCount := mysql_num_rows(Res); // Hent antallet af rækker i vores resultat sæt.
if RowCount > 0 then
begin // Hvis vi har et resultat, så ->
Row := mysql_fetch_row(Res); // Hent rækken
Result := Row[0]; // hent Name (index 0) og returner det til kalderen.
end;
mysql_free_result(Res); // Frigør resultat sættet (fra hukommelsen).
end;
if (FMySQL <> nil) then
mysql_close(FMySQL); // Luk vores forbindelse.
end;
Nu spørger jeg bare dumt, hver gang jeg skal hente en enkelt ting ud fra min database, skal jeg så skriv al den kode, bare med en anden forspørgsel??
Hilsen
Martin Dybdal (Dybber)
Hej Martin,
Jeg ville nok pakke noget af alt denne funktionalitet ind i en klasse som kan skabe forbindelsen til databasen og give dig nogle funktioner til at sende SQL'en.
Jeg har lave en klasse som sørgerfor at:
- Connect,
- Disconnect,
- Select,
- Delete,
- Update,
- Insert.
Her er koden (unit'en skal gemmes som mysql_database.pas):
unit mysql_database;
interface
uses
ContNrs,
Classes,
MySql;
type
TMySqlDatabase = class(TObject)
private
FLastError : Integer;
FLastErrorMessage : String;
FHost : String;
FDatabase : String;
FUser : String;
FPassword : String;
FConnected : Boolean;
protected
FMySQL : PMYSQL;
FMyTime : longword;
procedure SetError(AError : Integer; AErrorMsg : String);
public
constructor Create;
destructor Destroy; override;
function Connect : Boolean;
procedure Disconnect;
function Select(ASql : String) : TObjectList;
function Insert(ASql : String) : Int64; // id
function Delete(ASql : String) : Boolean;
function Update(ASql : String) : Boolean;
property Host : String read FHost write FHost;
property Database : String read FDatabase write FDatabase;
property User : String read FUser write FUser;
property Password : String read FPassword write FPassword;
property IsConnected : Boolean read FConnected;
property LastError : Integer read FLastError;
property LastErrorMessage : String read FLastErrorMessage;
end;
implementation
constructor TMySqlDatabase.Create;
begin
SetError(0, '');
FHost := '';
FDatabase := '';
FUser := '';
FPassword := '';
FMyTime := 30;
FMySQL := nil;
FConnected := False;
end;
destructor TMySqlDatabase.Destroy;
begin
Disconnect;
inherited Destroy;
end;
procedure TMySqlDatabase.SetError(AError : Integer; AErrorMsg : String);
begin
FLastError := AError;
FLastErrorMessage := AErrorMsg;
end;
function TMySqlDatabase.Connect : Boolean;
var
Session : PMYSQL;
begin
if (not FConnected) then
begin
FMySQL := mysql_init(nil); // initalisere en MySQL session.
mysql_options(FMySQL, MYSQL_OPT_CONNECT_TIMEOUT, @FMyTime);
Session := mysql_real_connect(FMySQL, PChar(FHost), PChar(FUser),
PChar(FPassword), PChar(FDatabase), 0, nil, 0);
FConnected := (Session <> nil);
end;
Result := FConnected;
end;
procedure TMySqlDatabase.Disconnect;
begin
if (FConnected) then
begin
mysql_close(FMySQL);
FConnected := False;
end;
end;
function TMySqlDatabase.Select(ASql : String) : TObjectList;
var
Res : PMYSQL_RES;
Row : PMYSQL_ROW;
RowCount, I : Integer;
ColCount, C : Integer;
RowItem : TStringList;
begin
Result := TObjectList.Create(True);
if (FConnected) then
begin
if (mysql_real_query(FMySQL, PChar(ASql), length(ASql)) = 0) then
begin // Vores forspørgelse gik godt.
Res := mysql_store_result(FMySQL); // Hent resultat sættet fra MySql.
RowCount := mysql_num_rows(Res); // Hent antallet af rækker i vores resultat sæt.
ColCount := mysql_num_fields(Res); // Hent antallet af kolonner i vores resultat sæt.
for I := 0 to RowCount-1 do
begin // Hvis vi har et eller flere resultater, så ->
RowItem := TStringList.Create;
Row := mysql_fetch_row(Res); // Hent rækken
for C := 0 to ColCount-1 do
begin // for hver kolonne i vores række ->
RowItem.Add(Row[C]); // Gem kolonne værdien.
end;
Result.Add(RowItem); // Gem vores row...
end;
mysql_free_result(Res); // Frigør resultat sættet (fra hukommelsen).
end;
end;
end;
function TMySqlDatabase.Insert(ASql : String) : Int64; // id
begin
Result := -1;
if (FConnected) then
begin
if (mysql_real_query(FMySQL, PChar(ASql), length(ASql)) = 0) then
Result := mysql_insert_id(FMySQL)
else
SetError(mysql_errno(FMySql), mysql_error(FMySql));
end;
end;
function TMySqlDatabase.Delete(ASql : String) : Boolean;
begin
if (FConnected) then
begin
Result := (mysql_real_query(FMySQL, PChar(ASql), length(ASql)) = 0);
if (not Result) then
SetError(mysql_errno(FMySql), mysql_error(FMySql));
end
else
Result := False;
end;
function TMySqlDatabase.Update(ASql : String) : Boolean;
begin
Result := False;
if (FConnected) then
begin
if (mysql_real_query(FMySql, PChar(ASql), Length(ASql)) = 0) then
Result := (mysql_affected_rows(FMySql) > 0)
else
SetError(mysql_errno(FMySql), mysql_error(FMySql));
end;
end;
end;
Jeg har ikke testet klassen, men du burde nok kunne rette evt. små fejl.
Når du nu skal bruge klassen skal du gøre det på følgende måder:
procedure TestDB;
var
DB : TMySqlDatabase;
Res : TObjectList;
Row : TStringList;
R,C : Integer;
ID : Int64;
begin
DB := TMySqlDatabase.Create;
DB.Host := 'localhost';
DB.Database := 'MinDB';
DB.User := 'Migselv';
DB.Password := 'mitpassword';
if (DB.Connect) then
begin // Okay vi har nu forbindelse til database.
Res := DB.Select('SELECT * FROM Users');
if (Res <> nil) then
begin
for R := 0 to Res.Count-1 do
begin
Row := TStringList(Res.Items[R]); // Hent række
for C := 0 to Row.Count-1 do
begin
//DataStr := Row.Strings[C]; // hent første kolonne
end;
end;
Res.Free; // Dealloker resultatet.
end;
if (DB.Update('UPDATE SET Users.Name=''Michael'' WHERE Id=1') = False) then
begin // Fejl, så hent dem.
//DB.LastError // last error code.
//DB.LastErrorMessage // last error message.
end;
ID := DB.Insert('INSERT INTO Users(Name, Password) VALUES(''Michael'', ''Ingen'')');
if (ID <> -1) then
begin // Okay, nu har vi id'et på den nye user.
end
else
begin // Hvis tabellen som der indsættes i ikke har en autoincrement kolonne så skal
// ID ikke bruges til noget.
//DB.LastError // last error code.
//DB.LastErrorMessage // last error message.
end;
end;
// Ups, manglede lige at disconnecte og deallokere klassen :-)
DB.Disconnect;
DB.Free;
end;
Jeg håber det er noget du kan bruge...
Du kan evt. ændre i klassen så du får navnene på kolonnerne med tilbage ved en Select.
/Michael.
[Redigeret d. 06/10-03 09:07:59 af Michael Skovslund]