Sign in Join
Wiki copytemporary

MySQLDatabases: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Introduction
22
33This page will explain how to connect to a [[mysql|MySQL]] server using visual components.
44
55> **Note:** This page has been written a long time ago and may be out of date. Also, most of the concepts described here are not MySQL specific but apply to all SQLDB databases. Therefore, following the SQLdb Tutorial series mentioned below may be easier
66
77Note: see also these tutorials that teach data-bound controls, parameterized queries, database independent programming etc:
88
99- [[SQLdb Tutorial1]]
1010- [[SQLdb Tutorial2]]
1111- [[SQLdb Tutorial3]]
1212
1313They are written for all databases that support sqldb, including MySQL.
1414
1515If needed, see also [[mysql|mysql#SQLDB_tutorials_and_example_code]] for yet more tutorials (that are also written a long time ago.
1616
1717## Available Components
1818
1919### SQLdb Components
2020
2121In any even vaguely recent version of Lazarus, the SQLDB components are installed by default.
2222
2323![](/wiki-images/c/c5/Sqldbcomponents.png%E2%80%8E)
2424
2525On the SQLDB tab you will find:
2626
2727- Various connectors, including [[TMySQL40Connection]]..[[TMySQL56Connection]] (or perhaps even newer versions) and the most versatile of all [[TSQLConnector]] that may load any of the mysql/oracle/postgres/mssql/interbase/firebird/odbc drivers.
2828- [[TSQLQuery]]
2929
3030If the SQLDB tab is missing, have a look at [[Install Packages]] for an "Install Howto".
3131
3232## Explanation of the used components
3333
3434### TMySQLConnection
3535
3636The TMySQLConnection is used to store parameters to connect to the database server. It enables you to set the host to connect to, and the userid and password to use in the connection. Another property of the TMySQLConnection is used to indicate the database you want to use. The 'LoginPrompt' is not functional yet, so make sure that next to the HostName and DatabaseName the UserName and Password properties have values as well before you try to open the connection. Be sure to use a TSQLTransaction as well and connect it to your MySQLConnection by setting the Transaction property, or you will not be able to open a SQLQuery.
3737
3838> **Note:** As indicated above, there are various MySQLConnection components that differ in version number. The version number **must** match the version number of the client library you use to connect to your server. So if you are running a MySQL 5.1 server but use a MySQL 5.0 client, use the TMySQL50Connection.
3939
4040You should check MySQL documentation to make sure the combination between client version and server version is supported - e.g. you may well have problems connecting to a 4.0 server using a 5.x client.
4141
4242In all cases put a copy of libmysql.dll *and any other required files/dlls*
4343
4444- in your Lazarus directory and the same directory as your project files or
4545- in the Windows system directory (if you don't want to keep copying files). Note that on 64 bit Windows you have to put the 32 bit library in SysWOW64, while 64 bit libraries go into System32.
4646
4747### TSQLTransaction
4848
4949A [[TSQLTransaction]] is needed for some internal housekeeping. A SQLTransaction is automatically activated when you open a dataset using it. Closing a connection also deactivates the related transaction and closes all datasets using it.
5050
5151### TSQLQuery
5252
5353[[TSQLQuery]] is used to execute SQLstatements on the server. You can retrieve data by setting the SQL to some SELECT statement and call the Open method. Or you can manipulate data by issuing some an INSERT, DELETE or UPDATE statement. In the latter case you should not use the Open method but the ExecSQL method.
5454
5555### TDataSource
5656
5757A [[TDataSource]] provides the connection between the visible data aware components like DBEdit, DBGrid and a dataset. It makes the data available for the data aware components to display. A datasource can only be connected to a single dataset at a time but there can be several data aware components connected.
5858
5959### TDBGrid
6060
6161A [[TDBGrid]] can be used to present the data retrieved by a Dataset. The DBGrid needs a datasource to connect to a dataset. When the dataset is opened, the DBgrid will automatically be populated with the data.
6262
6363## Our program
6464
6565### The basics
6666
6767We will try to make a program based on the one made [[Lazarus Database Tutorial/nl|here (in Dutch)]] which is based on the [[Lazarus Database Tutorial|original (in English)]] by Chris.
6868
6969### The main form
7070
7171We will use the same main screen and build all functionality from scratch :) As you will see there is a lot less to take care of, because the components really take away all the hard stuff! So lets start by making a screen that looks like this.
7272
73-![`Trymysql.png`](/wiki-images/2/28/Trymysql.png)
73+```text
74+image:Trymysql.png
75+```
7476
7577From the SQLdb-tab place a [[TMySQL56Connection]] ![](/wiki-images/9/97/Tmysql56connection.png) (or other mysql-client version) a [[TSQLTransaction]] ![](/wiki-images/b/bd/Tsqltransaction.png) and a [[TSQLQuery]] ![](/wiki-images/b/bb/Tsqlquery.png) on this form. Don't change the default names given to this components. Except for the connection component. To make this article the same for all versions of MySQL, name your TMySQL##Connection component: `MySQLConnection1`. We have to link these components together so they can do their job. So the following properties have to be set:
7678
7779| | | |
7880|------------------|--------------|------------------|
7981| **Component** | **Property** | **Value** |
8082| MySQLConnection1 | Transaction | SQLTransaction1 |
8183| SQLTransaction1 | Database | MySQLConnection1 |
8284| SQLQuery1 | Transaction | SQLTransaction1 |
8385| SQLQuery1 | Database | MySQLConnection1 |
8486
8587The Transaction-property of SQLQuery1 will automatically be set if you have set the Transaction property of MySQLConnection1 first. When you set this, you will notice that SQLTransaction1.Database has been set to MySQLConnection1.
8688
8789As said earlier: Make sure you are using the correct Connection component for your version of MySQL server.
8890
8991### The code
9092
9193As you can see in the screen dump the only buttons available on start of the program are "Connect to server" and "Exit". For the other buttons to work we need more information so these are disabled. We could decide to disable "Connect to Server" as well until the information for the host, username and password has been given. I decided against this because our user might think: "Nothing seems possible, so let's hit exit." :)
9294
9395Before I start giving you any code I would like to stress that there should be more exception handling in the code. Critical sections should be placed in
9496
95-`try ... finally`
97+```text
98+try ... finally
99+```
96100
97101or
98102
99-`try ... except`
103+```text
104+try ... except
105+```
100106
101107constructions.
102108
103109#### Connect to a server
104110
105111The first thing we have to do is get connected to our server. As when connecting we don't know what databases are available on the server we will ask for a list of databases on connecting. However there is one catch, to make the connection we have to enter a valid DatabaseName in the properties of the MySQLConnection. You will see in the code that I am using the "mysql" database. This database is used by mysql for some housekeeping so it will always be there.
106112
107113``` pascal
108114procedure TFormTryMySQL.ConnectButtonClick(Sender: TObject);
109115begin
110116 // Check if we have an active connection. If so, let's close it.
111117 if MySQLConnection1.Connected then CloseConnection(Sender);
112118 // Set the connection parameters.
113119 MySQLConnection1.HostName := HostEdit.Text;
114120 MySQLConnection1.UserName := UserEdit.Text;
115121 MySQLConnection1.Password := PasswdEdit.Text;
116122 MySQLConnection1.DatabaseName := 'mysql'; // MySQL is allways there!
117123 ShowString('Opening a connection to server: ' + HostEdit.Text);
118124 MySQLConnection1.Open;
119125 // First lets get a list of available databases.
120126 if MySQLConnection1.Connected then begin
121127 ShowString('Connected to server: ' + HostEdit.Text);
122128 ShowString('Retrieving list of available databases.');
123129 SQLQuery1.SQL.Text := 'show databases';
124130 SQLQuery1.Open;
125131 while not SQLQuery1.EOF do begin
126132 DatabaseComboBox.Items.Add(SQLQuery1.Fields[0].AsString);
127133 SQLQuery1.Next;
128134 end;
129135 SQLQuery1.Close;
130136 ShowString('List of databases received!');
131137 end;
132138end;
133139```
134140
135141The first thing we do is check to see if we are connected to a server, if we are then we call a private method "CloseConnection". In this method some more housekeeping is done. like disabling buttons and clearing comboboxes and listboxes. Then we set the necessary parameters to connect to server.
136142
137143
138144*Throughout our program you may see calls to ShowString. This method adds a line to the memo on our form which acts like a kind of log.*
139145
140146With the parameters set, we can connect to the server. This is done by calling
141147
142148``` pascal
143149MySQLConnection1.Open;
144150```
145151
146152In a proper application one would place this in an exception handling construct to present a friendly message to the user if the connection failed. When we are connected we want to get a list of databases from the server. To get data from the server a TSQLQuery is used. The SQL property is used to store the SQL-statement send to the server. MySQL knows the "SHOW DATABASES" command to get the list of databases. So after we have set the SQL-text, we call
147153
148154``` pascal
149155SQLQuery1.Open;
150156```
151157
152158On MySQL5 set this to correct error with SQL syntax:
153159
154160``` pascal
155161SQLQuery1.ParseSQL := False;
156162SQLQuery1.ReadOnly := True;
157163```
158164
159165The result set of a SQLQuery can be examined through the fields property. As you can see we iterate through the records by calling
160166
161167``` pascal
162168SQLQuery1.Next;
163169```
164170
165171When we have added all available databases to our combobox, we close the SQLQuery again.
166172
167173#### Selecting a database
168174
169175If the user selects a database in the DatabaseComboBox we enable the "Select Database" button. In the OnClick event of this button we set the DatabaseName of MySQLConnection1, and request a list of tables. The last statement of this procedure enables the "Open Query" Button, so the user can enter a query in the "Command" Editbox and have it send to the server.
170176
171177``` pascal
172178procedure TFormTryMySQL.SelectDBButtonClick(Sender: TObject);
173179begin
174180 // A database has been selected so lets get the tables in it.
175181 CloseConnection(Sender);
176182 if DatabaseComboBox.ItemIndex <> -1 then begin
177183 with DatabaseComboBox do
178184 MySQLConnection1.DatabaseName := Items[ItemIndex];
179185 ShowString('Retreiving list of tables');
180186 SQLQuery1.SQL.Text := 'show tables';
181187 SQLQuery1.Open;
182188 while not SQLQuery1.EOF do begin
183189 TableComboBox.Items.Add(SQLQuery1.Fields[0].AsString);
184190 SQLQuery1.Next;
185191 end;
186192 SQLQuery1.Close;
187193 ShowString('List of tables received');
188194 end;
189195 OpenQueryButton.Enabled := True;
190196end;
191197```
192198
193199MySQL has a special command to get a list of tables, comparable to getting the list of databases, "show tables". The result of this query is handled in the same way as the list of databases and all the tables are added to the TableComboBox. You might wonder why we do not open the connection again before opening the query? Well, this is done automatically (if necessary) when we activate the SQLQuery.
194200
195201#### Fields in a table
196202
197203In MySQL you can again use a form of "SHOW" to get the fields in a table. In this case "SHOW COLUMNS FROM \<tablename\>". If the user picks a table from the TableComboBox the OnChangeEvent of this ComboBox is triggered which fills the FieldListbox.
198204
199205``` pascal
200206procedure TFormTryMySQL.TableComboBoxChange(Sender: TObject);
201207begin
202208 FieldListBox.Clear;
203209 SQLQuery1.SQL.Text := 'show columns from ' + TableComboBox.Text;
204210 SQLQuery1.Open;
205211 while not SQLQuery1.EOF do begin
206212 FieldListBox.Items.Add(SQLQuery1.Fields[0].AsString);
207213 SQLQuery1.Next;
208214 end;
209215 SQLQuery1.Close;
210216end;
211217```
212218
213219As well as the names of the fields, the result set contains information on the type of field, if the field is a key, if nulls are allowed and some more.
214220
215221#### Showing the data
216222
217223Well as we said we would use components to get connected to the database, lets use some components to show the data as well. We will use a second form to show a grid with the data requested by the user. This form will be shown when the user typed a SQL command in the "Command" editbox and afterwards clicks the "Open Query" button. This is the OnClick event:
218224
219225``` pascal
220226procedure TFormTryMySQL.OpenQueryButtonClick(Sender: TObject);
221227begin
222228 ShowQueryForm := TShowQueryForm.Create(self);
223229 ShowQueryForm.Datasource1.DataSet := SQLQuery1;
224230 SQLQuery1.SQL.Text := CommandEdit.Text;
225231 SQLQuery1.Open;
226232 ShowQueryForm.ShowModal;
227233 ShowQueryForm.Free;
228234 SQLQuery1.Close;
229235end;
230236```
231237
232238The ShowQueryForm looks like this:
233239
234240![](/wiki-images/4/47/Mysqlshow.png)
235241
236242and contains a
237243
238244| | | |
239245|----|----|----|
240246| [[TPanel]] | Align | alBottom |
241247| [[TDataSource]] | | |
242248| [[TDBGrid]] | Align | alClient |
243249| | DataSource | DataSource1 |
244250| [[TButton]] | Caption | Close |
245251
246252The button is placed on the panel. What happens in the "Open Query" OnClick is this. First we create an instance of TShowQueryForm. Secondly we set the DataSet property of the DataSource to our SQLQuery1. Then we set the SQLQuery SQL command to what the user entered in the "Command" editbox and open it. Then the ShowQueryForm is shown modally, this means that it will have the focus of our application until it is closed. When it is closed, we "free" it and close SQLQuery1 again.
247253
248254The Form can be further enhanced by inserting a method for modifying the content of the [[TDataSet]] and ultimately the DataBase. A full version can be downloaded from <http://digitus.itk.ppke.hu/~janma/lazarus/MySql5Test.tar.gz> (with thanks to Arwen and JZombi from the Lazarus MySQL Forum) but the relevant details are as follows:
249255
250256Add a Button at the bottom of the ShowQuery Form named AddButton and with Caption 'Add'. Create a method for AddButtonClick like this:
251257
252258``` pascal
253259procedure TShowQueryForm.AddButtonClick(Sender: TObject);
254260begin
255261 DataSource1.DataSet.Append;
256262end;
257263```
258264
259265Change the code for OpenQueryButtonClick to allow for updates to the database when we finish with the Query Form.
260266
261267``` pascal
262268procedure TFormTryMySQL.OpenQueryButtonClick(Sender: TObject);
263269begin
264270 ShowQueryForm := TShowQueryForm.Create(nil);
265271 try
266272 ShowQueryForm.DataSource1.DataSet := SQLQuery1;
267273 // We will write in the database, so let's set ReadOnly to false,
268274 // and for that we need to set ParseSQL true
269275 SQLQuery1.ParseSQL:=true;
270276 SQLQuery1.ReadOnly:=false;
271277 SQLQuery1.SQL.Text := CommandEdit.Text;
272278 SQLQuery1.Open;
273279 ShowQueryForm.ShowModal;
274280 finally
275281 // set up update mode, and update database
276282 SQLQuery1.UpdateMode:=upWhereChanged;
277283 SQLQuery1.ApplyUpdates;
278284 SQLTransaction1.Commit;
279285 ShowQueryForm.Free;
280286 SQLQuery1.Close;
281287 // set read-only and parsesql back to default
282288 SQLQuery1.ParseSQL:=false;
283289 SQLQuery1.ReadOnly:=true;
284290 end;
285291end;
286292```
287293
288294We can now add records to the Database. If we add a TDBNavigator to the ShowQuery Form we can move around the Data Grid more easily, and edit records; the database gets updated with our changes each time we close the ShowQuery Form, and we can test this by opening it up again to inspect the database.
289295
290296If you want to be able to DELETE or otherwise modify records on the original database (ie make sure changes you make to the local dataset get committed back to the database) then you need to have one column in your database table that is a primary key autoincremented, as the 'delete' method requires to be able to generate a 'where' clause when writing instructions back to the database, to identify the records selected for deletion. So use the following code in your MySQL client (it can all be typed on one line, but line breaks have been added for clarity):
291297
292298``` sql
293299ALTER TABLE TRESTRIG
294300ADD COLUMN AUTOID INT
295301PRIMARY KEY AUTO_INCREMENT;
296302```
297303
298304and then you will find that the Delete button on the navigator works.
299305
300306## Sources
301307
302308The sources for this project can be downloaded [here](http://prdownloads.sourceforge.net/lazarus-ccr/mysql_demo_20050408.tar.gz?download) For more demo projects see [sourceforge](http://sourceforge.net/project/showfiles.php?group_id=92177&package_id=148359)
303309
304310## See also
305311
306312- [[mysql]]
307313
308314---
309315*From the Free Pascal wiki, page "MySQLDatabases", as it stood on 2020-02-20 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history