Jump to content
Columbo

Help to find database error

Recommended Posts

I’m trying to learn Delphi 7 and at the moment I am trying to figure out how to access and retrieve data from a SQLite database.  I found a short pdf tutorial and I followed the instructions but it is flagging a Undeclared identifier: ‘ShowSelectResults’.   I have gone over the code several times comparing it to the code in the pdf tutorial and I can’t find anything different.  The line that is highlighted in Delphi is ShowSelectResults();  I assumed that it might be something wrong in the procedure TDatabaseTutorial.ShowSelectResults(); but if it is I can’t figure out where, unless there is an error in the tutorial.   Can anyone give me a hint as to what is causing this?

 

Here is my code:


unit DatabaseTutorial_u;



 

interface



 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, DBXpress, FMTBcd, DB, SqlExpr, StdCtrls;



 

type

  TfrmDatabaseTutorial = class(TForm)

    btnConnect: TButton;

    btnExecute: TButton;

    SQLConnection1: TSQLConnection;

    memOutput: TMemo;

    SQLQuery1: TSQLQuery;

    procedure btnConnectClick(Sender: TObject);

    procedure btnExecuteClick(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;



 

var

  frmDatabaseTutorial: TfrmDatabaseTutorial;



 

implementation



 

{$R *.dfm}



 

procedure TfrmDatabaseTutorial.btnConnectClick(Sender: TObject);

begin

  SQLConnection1.Params.Add('D:\Borland Delphi\Test Projects\Database Tutorial\Data\Dat2.sqlite');

  try

    //Establish the connection

    SQLConnection1.Connected := true;

    btnExecute.Enabled := true;

    memOutput.Text := 'Connection Established!';

  except

    on E: EDatabaseError Do

    ShowMessage('Exception raised with message' + E.Message);

  end;

end;



 

procedure TfrmDatabaseTutorial.btnExecuteClick(Sender: TObject);

var

query : String;



 

begin

  memOutput.ClearSelection;

  //Set up a Query

  query := 'SELECT * FROM hline1;';

  try

  //Assign the query to the object SQLQuery1

  SQLQuery1.SQL.Text := query;

  SQLQuery1.Active := true;

  except

    on E: Exception Do

      memOutput.Text := 'Exception raised with message:' + E.Message;

  end;

  //Show the result of the query in memOutput

  ShowSelectResults();

end;



 

procedure TDatabaseTutorial.ShowSelectResults();

var

headline : TStringList;



 

i : integer;

currentField: Tfield;

currentLine : string;



 

begin

  If not SQLQuery1.IsEmpty Then

  begin

  SQLQuery1.First;

  headline := TStringList.Create;

  try

    SQLQuery1.GetFieldNames(headline);

    While not SQLQuery1.Eof Do

    begin

      currentLine := ";

      for i := 0 to hline1.Count -1 Do

        begin

        currentField := SQLQuery1.FieldByName(headline(i));

        currentLine := currentLine + ' ' + currentField.AsString;

      end;

      

      memOutput.Lines.Add(currentLine);

      SQLQuery1.Next;

    end;

    headline.Free;

    end;

  end;

end.

 

 

Edited by Columbo
typo

Share this post


Link to post

You have to add ShowSelectedResults to the class definition.

 

Simplest is to throw it in the public declaration section

 

 public

    { Public declarations }
    
    procedure ShowSelectedResults;

 

It's likely you need to change hline1 to headline below too:

for i := 0 to hline1.Count -1 Do

Share this post


Link to post

I made the changes that you suggested but it still flags the same error, Undeclared identifier: ‘ShowSelectResults’.

 

Here is the change that I made:


unit DatabaseTutorial_u;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DBXpress, FMTBcd, DB, SqlExpr, StdCtrls;

type
  TfrmDatabaseTutorial = class(TForm)
    btnConnect: TButton;
    btnExecute: TButton;
    SQLConnection1: TSQLConnection;
    memOutput: TMemo;
    SQLQuery1: TSQLQuery;
    procedure btnConnectClick(Sender: TObject);
    procedure btnExecuteClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ShowSelectedResults;
  end;

 

I also changed hline1 to headline as you suggested.

 

Share this post


Link to post
4 hours ago, Columbo said:

I’m trying to learn Delphi 7 and at the moment I am trying to figure out how to access and retrieve data from a SQLite database. 

Can I make two suggestions?
First one, if you absolutely want to keep Delphi 7 use, try to install ZEOSLIB (aka  ZEOSDBO) and use this data access component suite instead of DBExpress

Second, try Delphi 11 community, with his Firedac components,    

Share this post


Link to post

Thanks Serge_G. 

 

Delphi 7 actually belongs to my son so I am using his computer to see if I can learn Delphi before making such a purchase.  I looked at Delphi 11 Community and downloaded it but it won't install.  I am still using Windows 7 Professional on my computer, (I'm not a fan of Windows 10 or 11).  I am pretty sure that the Delphi web site said that Delphi 11 was compatible with Windows 7 but it won't install.  When I enter the Serial number that they emailed to me it says that the Serial number is invalid.  I tried 3 times uninstalling and reinstalling but continue to have the same problem.  One thing that I don't understand is that at one point a dialog came up saying that I was using Windows 6.1 which I have never heard of.  I gave up on trying to install it.  I will Google ZEOSDBO and try that as you kindly suggested. 

 

Since I posted this I have downloaded ZeosLib but any instructions that I have found about installing and using it seems to always refer to Firebird.  I want to use it for SQLite.

Edited by Columbo

Share this post


Link to post

The problem is the procedure is declared to a class that does not exist:

 

Quote

procedure TDatabaseTutorial.ShowSelectResults();

Should be:

procedure TfrmDatabaseTutorial.ShowSelectResults();

 

Share this post


Link to post

Thanks Tom,  I replaced the line

 


procedure TDatabaseTutorial.ShowSelectResults();

 

with

 


procedure TfrmDatabaseTutorial.ShowSelectResults();

 

but error still exists.

Share this post


Link to post

You need to make the names match: 

procedure TfrmDatabaseTutorial.ShowSelectedResults();

Selected not Select

Share this post


Link to post
48 minutes ago, ioan said:

You need to make the names match: 


procedure TfrmDatabaseTutorial.ShowSelectedResults();

Selected not Select

I tried that but it now flags an error at

 


private
    { Private declarations }
  public
    { Public declarations }
    procedure TfrmDatabaseTutorial.ShowSelectedResults();
  end;

 

The actual procedure is:

 


procedure TDatabaseTutorial.ShowSelectResults();

 

If I change the actual procedure to match the change in the Public delarations using 'ShowSelectedResults' I still get the error in the Public declarations.

 

Edited by Columbo

Share this post


Link to post

It's easy to get confused at first. What ioan is saying the procedure "ShowSelectResults" or "ShowSelectedResults" you decide has to match. However, in the implementation section at the top inside your class TfrmDatabaseTutorial in the public section you do not use the class name just

public
    { Public declarations }
    procedure ShowSelectedResults;

Down below in the implementation section where you write your code you need the class name then a period then the procedure with exact spelling

procedure TDatabaseTutorial.ShowSelectedResults();
begin
  //code
end;

If you get rid of the class name from the implementation section and just leave "procedure ShowSelectedResults;" then with your cursor on the line press ctrl + shift + c Delphi will create the implementation section for you and you don't have to worry about spelling. 

Share this post


Link to post

look at the event handlers Delphi created btnConnectClick(Sender: TObject) and btnExecuteClick(Sender: TObject) to see this. You can use ctrl + shift + up or down arrow to toggle between interface and implementation sections. Also it doesn't hurt but the () are not needed if you have no parameters.

Share this post


Link to post

Thanks Gary.  In the declaration section I put the following code:

 

  private
    { Private declarations }
  public
    { Public declarations }
    procedure TfrmDatabaseTutorial.ShowSelectResults;
  end;

 

and in the implementation I put the following code:

 


procedure TfrmDatabaseTutorial.ShowSelectResults;
var
headline : TStringList;

...

 

but I am still getting the error flagged on the line in the Public declarations saying 'Undeclared Identifier: 'TfrmDatabaseTutorial'.

 

 

Share this post


Link to post
16 minutes ago, Columbo said:

In the declaration section I put the following code:

...

and in the implementation I put the following code:

...

but I am still getting the error flagged on the line in the Public declarations saying 'Undeclared Identifier: 'TfrmDatabaseTutorial'.

REMOVE 'TfrmDatabaseTutorial.' from the DECLARATION!

  public
    { Public declarations }
    procedure ShowSelectResults; // <-- NO TfrmDatabaseTutorial here!
  end;

It belongs only in the IMPLEMENTATION:

procedure TfrmDatabaseTutorial.ShowSelectResults; // <-- ONLY here!
var
  headline : TStringList;
...
end;

 
Edited by Remy Lebeau

Share this post


Link to post

Yes! What Remy said!

Your form is your class and defined in the interface section of the file. This is just the description or declaration of the class, you write the code later in the implementation section

type
  TfrmDatabaseTutorial = class(TForm) //<- Class name
    btnConnect: TButton;
    btnExecute: TButton;
    SQLConnection1: TSQLConnection;
    memOutput: TMemo;
    SQLQuery1: TSQLQuery;
    procedure btnConnectClick(Sender: TObject); //<- procedures of your class no need for TfrmDatabaseTutorial
    procedure btnExecuteClick(Sender: TObject); //<- procedures of your class no need for TfrmDatabaseTutorial
  private
    { Private declarations }
  public
    { Public declarations }
    procedure ShowSelectedResults;//<- procedures of your class no need for TfrmDatabaseTutorial
  end; // <- Definition of your class ends here

When you write your code the unit needs to know what class your procedure belongs to since you can have multiple classes,  so you need it here:

 

implementation

 

TDatabaseTutorial needs to be here so compiler knows what class the procedure belongs to. Multiple classes can have the same procedure names and often do so you have to distinguish them.

procedure TDatabaseTutorial.ShowSelectResults; 
begin
  //code
end;

 

Share this post


Link to post

That has got me past the error.  Thank you very much guys.  I've only been playing with Delphi 7 for 3 days and it is somewhat confusing at times.

And now,...  on to the next error.  🙂  Trying to assign an empty string to a variable.

 

Thanks to all for your help and patience.  Very much appreciated.

 

Share this post


Link to post

Thanks Gary.  Actually I did watch Gerhard's videos. What I like about his videos is that he takes his time and explains everything.  I found that a lot of videos that I had looked at previously, the teacher went too fast for a beginner to keep up.  They know what they are doing so they have the cursor moving all over the place clicking this and clicking that and I find it difficult to follow.  Gerhard is not like that and takes his time.  I still have a few of his videos to watch yet but I didn't see any that dealt with databases. 

 

I used to program in dBaseIII and Clipper back in 1997 and I wrote a program where you enter someone's name, the day, month and year of their birth and the program would do a printout showing their birthstone, birth flower, astological sign, planet and element, 3 newspaper headlines that appeared on their birthday, the Stanley cup winner for that year, The Greay Cup winner, the Academy Award best Actor and actress, best movie, the U.S President at that time, the Canadian Prime Minister, and the price of a loaf of bread, quart of milk, a dozen eggs, a pound of butter, average price of a home, average price of an automobile and the average price of gas.  I wanted to try writing the same program in Delphi so I have to get to know how to manipulate databases in Delphi.  I took my .DBF database files and converted them to SQLite so I still have the data for all birth dates from the year 1900 to 1997.  I will have to add the data from 1998 to present.  A lot of work and research but fun in the end.  Besides, I'll be 82 in January so, hopefully, it will help to keep my mind sharp.

 

Thanks again Gary.  You have been very helpful.

 

 

 

Edited by Columbo

Share this post


Link to post

I started with Lotus Approach and dBase files 🙂 

Just wondering, you know while your project is great for learning Delphi you can do the same thing with components and hardly any code? That's what got me interested in Delphi in the beginning.

Drop a TDBGrid and TDataSource on the form, connect the Grids DataSource property to the TDataSource, set the DataSource's DataSet property to your Query and when you open the Query it populates the Grid automatically including FielNames as headers.

 

Share this post


Link to post

Personally, I think it would be easier to use Firebird. I don't even use another one. I also tried SQLite, but quickly dismissed it.

  • Like 1

Share this post


Link to post
5 hours ago, Gary said:

I started with Lotus Approach and dBase files 🙂 

 

Interesting that you started with dBase as well. I don't know much about Lotus Approach although I knew of it back in the day.  I am assuming that TDBGrid  gives you a MS Access style layout?  The program that I wrote in Clipper was called "This Day In History" and it did not display anything.  It uses 7 databases and once the person's name and birth date is entered it goes directly to the printer and prints out the data for that date in history. 

 

I did another program in Purebasic called "Prehistoric Life" and it uses a lot of text fields, a memo field, 2 image boxes and a few buttons.  It displays data and pictures on 112 animals and sea creatures that lived in prehistoric times.  That might also be a good program to learn Delphi with.  I did the same program when I was learning Python.

 

Share this post


Link to post

Hi stano,  I don't know anything about Firebird but I will look into it.  I seen it mentioned a number of times in posts related to FireDAC.

 

Share this post


Link to post

Agree @Stano Firebird SQL is a very good RDBMS, all my pro GPAO suite use it. SQLite has also some advantages for mono-station programs

On 11/28/2023 at 4:58 PM, Columbo said:

Since I posted this I have downloaded ZeosLib but any instructions that I have found about installing and using it seems to always refer to Firebird.  I want to use it for SQLite.

ZeosLib can be used with many database system, not only firebird ones
 

Quote

The ZeosLib is a set of database components for MySQL, MariaDB, PostgreSQL, Interbase, Firebird, MS SQL Server, SAP Adaptive Server Enterprise and Adaptive Server Anywhere (previously Sybase), Oracle and SQLite for Delphi

You have only to change Zconnection.protocol parameter to sqlite (or sqlite-3).

If you find more doc ZEOSDBO+Firebird you can apply all (or at least a good part of) the doc to SQlite as well.

Effectively when I wrote (never finished, but on the web) a (French) tutorial about ZEOS components my samples was Firebid ones also :classic_blush:

Edited by Serge_G

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×