Recent

Author Topic: Lazarus Database Tutorials  (Read 10595 times)

guest48180

  • Guest
Lazarus Database Tutorials
« on: December 05, 2012, 11:05:45 pm »
As BigChimp will attest to, I didn't follow the tutorials step by step when I first started them. And that gave me a lot trouble, mostly a complete lack of understanding. So I went back and did them the right way, and things were looking good as they were explained very well. I did the tutorials using a db I created, one that I have interest in (it has two fields in it: a DB_KEY generated by Flamerobin, and NAME  (it has seven entries)), and ultimately had issues with the db updating. The DBNavigator seems useless to edit, delete, or post records. The refresh works fine though.
If i click into a cell to change the spelling of a name, let's say, then click edit on the navigator bar, do my edit and click post, then refresh, the editing is gone and field is back to the way it was when before I edited it. Crazy, that.
And if I do the same thing again except not refresh the DBGrid and instead click the "Show Data" button, I get an error:

An error occured while applying the updates in a record: SQLQuery1 : No update query specified and failed to generate one. (No fields for inclusion in where statement found).

Here's the code.

<code>
implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.SaveChanges;
// Save edits done by the user, if any.
begin
   try
      if SQLTransaction1.Active then
      // Only if we are within a started transaction...
      // otherwise you get "Operation cannot be performed
      // on an inactive dataset.
      begin
         SQLQuery1.ApplyUpdates; // Pass user-generated changes back to database
         SQLTransaction1.Commit; // ...and commit them using the transaction.
         // SQLTransaction1.Active now is False.
      end;
   except
     on E: EIBDatabaseError do
        begin
           MessageDlg('Error', 'A database error has occured (SaveChanges Procedure). Technical error message: ' +
                             E.Message, mterror, [mbOK], 0);
           editSQLParam.Text:= '';
        end;
   end;

end;

procedure TForm1.DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState
    );
begin
   // Check for Delete key being hit and delete the current response
   // as long as we're not editing data (in Editor Mode).
   if (key=VK_DELETE) and (not(DBGrid1.EditorMode)) then
   begin
      // delete current record and apply updates to db
      SQLQuery1.Delete;
      SQLQuery1.ApplyUpdates;
   end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   SaveChanges; // Saves changes and commits transaction
   try
        SQLQuery1.Close;
        if not IBConnection1.Connected then
        begin
        IBConnection1.UserName:= editUsername.Text;
       IBConnection1.Password:= editPassword.Text;
       IBConnection1.HostName:= editHost.Text;
       IBConnection1.DatabaseName:= editDatabaseName.Text;
        // Now that we've connected, we set the Edit Boxes
         // to ReadOnly so no further changes can be made.
         editHost.ReadOnly:= True;
         editDatabaseName.ReadOnly:= True;
         editUsername.ReadOnly:= True;
         editPassword.ReadOnly:= True;
        end;
        // Show all customer names, or filter for one
        if editSQLparam.Text = '' then
            SQLQuery1.SQL.Text:= 'select * from customer order by name'
        else
        begin
         SQLQuery1.SQL.Text:= 'select * from customer where name = :name';
         SQLQuery1.Params.ParamByName('name').AsString:= editSQLparam.Text;
        end;
        IBConnection1.Connected:= True; //By default, SQLQuery1.Close sets this to True
        SQLTransaction1.Active:= True;  //By default, SQLQuery1.Close sets this to True
        SQLQuery1.Open;
      {
       Make sure we don't get problems with inserting blank (=NULL) CUST_NO values, e.g.:
       Field CUST_NO is required, but not supplied
         We need to tell Lazarus that, while CUST_ID is a primary key, it is not required
       when inserting new records.
        }
      // SQLQuery1.FieldByName('cust_id').Required:= False;
      // DBGrid1.Columns[0].Visible:= False; // Hide the cust_id from the user as it is
                                          // the Primary Key
   except
     on E: EIBDatabaseError do
     begin
       MessageDlg('Error', 'A database error has occure. Technical error message: ' +
                         E.Message,mtError,[mbOK],0);
       editSQLParam.Text:= '';
     end;
   end;
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
   SaveChanges; // Save changes and commits transaction
   SQLQuery1.Close;
   { *************************************************
     I have omitted the next two lines of code because
       SQLQuery1.Close sets them to False anyway...
    SQLTransaction1.Active:= False;
         IBConnection1.Connected:= False;
   *************************************************** }
end;

end.
</code>

If anyone sees an error, please advise. This doesn't seem to be difficult at all, but I can't make it work...even after moving step-by-step through the tutorials. And I've been chopping at this tree all morning and ain't put a dent in it yet. It has me so frustrated that I downloaded QT earlier just to see if if using databases on it was easier. Thing is, I like using Pascal...and I really like Lazarus. I sure hope someone can help me with this.

Landslyde

denver

  • Jr. Member
  • **
  • Posts: 67
Re: Lazarus Database Tutorials
« Reply #1 on: December 05, 2012, 11:51:50 pm »
For the component SQLQuery1 , it has the following Properties you have to fill-in :

DeleteSQL
UpdateSQL
InsertSQL

Otherwise SQLQuery1 don't konw how to Update / Insert  / Delete a record.


BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Lazarus Database Tutorials
« Reply #2 on: December 06, 2012, 08:57:08 am »
You say "Flamerobin generates a DB_KEY column". Well that is sort of correct. It is actually generated by Firebird.
Whatever the case, it normally is never used - it is a hidden key (see e.g. http://www.firebirdfaq.org/faq301/) Flamerobin will only use it to distinguish rows if there is no primary key defined in the column.

You probably don't have a DB_KEY column defined in that table but just a NAME, without any primary key. Please define a primary key. The tutorials work with autonumber/generated primary keys: integer primary keys that in Firebird are backed by a generator/sequence and trigger. See the employee.fdb sample database for details or you can add such a PK column to an existing table quite easily in Flamerobin.

Without a primary key, FreePascal has no idea which row to update when you edit the grid, therefore Denver's advice that you need to use UpdateSQL etc is completely correct as you will need to spell it out for FreePascal.
However, that will require fiddling with RDB$_KEY, or not accepting duplicate NAME values or something. Much easier to just add a primary key and not having to specify UpdateSQL etc.
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Lazarus Database Tutorials
« Reply #3 on: December 06, 2012, 09:47:07 am »
Adding a generated/sequence/"autonumber" primary key (column named ID in this example):

1. In Flamerobin:
1.1 go to the table properties, summary, go to the fields, add an ID field if it doesn't exist, integer datatype, check NOT NULL; otherwise view details/edit ID field.
1.2 In the properties windows for ID, in the autoincrement section: select "Create new generator". Leave the name as is. Check Create trigger. Execute/apply etc
1.3 Add primary key constraint: go to the table properties, constraints, add primary key, name it what you want, select the ID column (which should have the

2. In SQL code (assuming table called NOPK) and an existing ID integer not null field:
Code: [Select]
SET TERM ^ ;
CREATE TRIGGER NOPK_BI FOR NOPK ACTIVE
BEFORE INSERT POSITION 0
AS
DECLARE VARIABLE tmp DECIMAL(18,0);
BEGIN
  IF (NEW.ID IS NULL) THEN
    NEW.ID = GEN_ID(GEN_NOPK_ID, 1);
  ELSE
  BEGIN
    tmp = GEN_ID(GEN_NOPK_ID, 0);
    if (tmp < new.ID) then
      tmp = GEN_ID(GEN_NOPK_ID, new.ID-tmp);
  END
END^
SET TERM ; ^

ALTER TABLE NOPK ADD CONSTRAINT PK_NOPK PRIMARY KEY (ID);
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

guest48180

  • Guest
Re: Lazarus Database Tutorials
« Reply #4 on: December 06, 2012, 05:55:33 pm »
Denver, BigChimp, I appreciate both of your inputs. I will look harder into this per your suggestions. I know this isn't as difficult as I'm making it to be...and I apologize for seeming to be the student of chaos to the world of programming databases  :D  This is the only part of all I do that is giving me fits and sleepless nights. Even my Irish Setter pup is unsure of me these days  :)  But I feel all this is slowly but surely coalescing into something that's beginning to make sense. And I really enjoyed going through the tutorials, Reinier. A lot of questions were answered by me just taking my time and doing what you asked me to do. Thanks.

Landslyde

guest48180

  • Guest
Re: Lazarus Database Tutorials
« Reply #5 on: December 06, 2012, 06:03:10 pm »
By the way, BigChimp, how do you get you code to come up in the scrollable window? I like that  :)

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Lazarus Database Tutorials
« Reply #6 on: December 06, 2012, 06:17:37 pm »
Thanks.

re the code: surround your code with code tags
begin:
[ followed by code followed by ]
end
[ followed by / followed by code followed by ]
or select the text & press the button next to the quotation button with a # on it.
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

 

TinyPortal © 2005-2018