Sign in Join
Wiki copytemporary

Lazarus Database Tutorial/nl: what changed

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

OldNewLine
11## Overzicht
22
33Deze paragraaf laat zien hoe je Lazarus kunt gebruiken met verschillende databases. Zoals je ziet zijn nog niet alle databases gedekt, dus... help mee om dit deel uit te breiden.
44
55## Lazarus en MySQL
66
77### MySQL werkend krijgen onder Linux of Windows
88
99Volg de instructies van het MySQL User Manual. Zorg er voor dat de mysqld service draait en dat alle mogelijke gebruikers (waaronder root, mysql, jijzelf en eventueel andere gebruikers) net zoveel rechten hebben als nodig is, vanaf net zoveel computers (hosts) als nodig is (waaronder 'localhost', de naam van de computer waarop MySQL draait en eventueel andere computers in je netwerk.) Het mag duidelijk zijn dat het het beste is als alle gebruikers gebruik maken van een paswoord. Controleer de werking van de database server op basis van de voorbeelden die in de handleiding worden gegeven. Controleer ook of alle gebruikers de door hen benodigde toegang hebben.
1010
1111### MySQL werkend krijgen met FPC in een terminal
1212
1313In de directory \$(FreePascal_directory)/packages/base/mysql/ staat een voorbeeld programma. Deze directory bevat ook de units mysql.pp, mysql_com.pp and mysql_version.pp. Voordat je het test script uitvoert, moet je een database genaamd "testdb" aanmaken. Dit kun je doen door in te loggen met behulp van de mysql monitor (als root met alle rechten) en het volgende SQL statement uit te voeren.
1414
15-`CREATE DATABASE testdb;`
15+```text
16+CREATE DATABASE testdb;
17+```
1618
1719zorg er dan voor dat alle gebruikers voldoende rechten hebben door commando's zoals het volgende:
1820
19-`GRANT ALL ON testdb TO johnny-user IDENTIFIED BY 'johnnyspassword'; `
21+```text
22+GRANT ALL ON testdb TO johnny-user IDENTIFIED BY 'johnnyspassword';
23+```
2024
2125uit te voeren. Er is een script genaamd mkdb, dat je nu moet uitvoeren:
2226
23-`sh ./mkdb`
27+```text
28+sh ./mkdb
29+```
2430
2531Waarschijnlijk mislukt dit omdat het systeem niet toestaat dat een anonieme gebruiker de database benadert. Wijzig het script nu zo dat de regel die de mysql client het script laat starten er zo uit ziet:
2632
27-`mysql -u root -p  ${1-testdb} << EOF >/dev/null`
33+```text
34+mysql -u root -p ${1-testdb} << EOF >/dev/null
35+```
2836
2937en probeer het script nogmaals uit te voeren, waarbij je het root paswoord invult op de prompt. Met een beetje geluk heb je nu de test database gemaakt. Controleer dit door het volgende mysql statement uit te voeren, vanuit je mysql monitor:
3038
31-`select * from FPdev;`
39+```text
40+select * from FPdev;
41+```
3242
3343Als het goed is zie je nu een tabel met de ID, username en email adressen van een paar van de FPC ontwikkelaars.
3444
3545Probeer nu het testprogramma testdb.pp uit te voeren. (Waarschijnlijk moet dit eerst nog gecompileerd worden en zal het de eerste keer niet lukken om het succesvol uit te voeren!!)
3646
3747Er kunnen een aantal redenen zijn waarom het programma geen verbinding kan maken met de mysql server:
3848
3949- Het systeem installeert een andere versie, bijv. mysql v4.0.15 en niet de versie 3 waarvoor het package is ontworpen.
4050
4151- Het programma heeft een geldige mysql gebruikersnaam en wachtwoord nodig om de database te benaderen.
4252
4353- De compiler moet weten waar het de mysql libraries kan vinden. (ALS JE DE MYSQL ONTWIKKEL LIBRARIES NOG NIET HEBT GEÏNSTALLEERD, DOE DAT DAN NU!)
4454
4555Als je een copy maakt van testdb.pp, bijvoorbeeld trydb.pp, in plaats van het origineel aan te passen, zullen de bestanden bij volgende CVS updates ook weer up to date worden. Ook kun je de bestanden van de mysql/ver40/ subdirectory kopieren naar de mysql/ directory. Hernoem ze dan naar mysql_v4.pp, mysql_com_v4.pp and mysql_version_v4.pp, en zorg ervoor dat je de gebruikte units in iedere file ook aanpast. Dus: wijzig het uses statement in trydb.pp in
4656
47-`uses mysql_v4`
57+``` pascal
58+uses mysql_v4
59+```
4860
4961en het statement in mysql_v4.pp in
5062
51-`uses mysql_com_v4`
63+``` pascal
64+uses mysql_com_v4
65+```
5266
5367Waarschijnlijk moet er aan /etc/fpc.cfg een regel toegevoegd worden die wijst naar de libraries:
5468
55-`-Fl/lib;/usr/lib`
69+```text
70+-Fl/lib;/usr/lib
71+```
5672
5773en moet in de /usr/lib directory een link naar de mysqlclient library gemaakt worden. Bij het installeren van de ontwikkel libraries wordt deze link al aangemaakt. Mocht deze link er onverhoopt niet zijn dan kun je deze op de volgende manier aanmaken:
5874
59-`ln -s libmysqlclient.so.12.0.0 lmysqlclient`
75+```text
76+ln -s libmysqlclient.so.12.0.0 lmysqlclient
77+```
6078
6179Controleer wel even de naam van jouw libraries. Voor de zekerheid kun je ook de volgende link aanmaken
6280
63-`ln -s libmysqlclient.so.12.0.0 mysqlclient`
81+```text
82+ln -s libmysqlclient.so.12.0.0 mysqlclient
83+```
6484
6585Sommigen moeten misschien de volgende link opnemen:
6686
67-`ln -s libmysqlclient.so.12.0.0 libmysqlclient.so`
87+```text
88+ln -s libmysqlclient.so.12.0.0 libmysqlclient.so
89+```
6890
6991Wijzig dan trydb.pp zodanig dat het de gebruiker details kent, door de host, user en paswoord als constanten op te nemen:
7092
71-`const`\
72-`  host : Pchar= 'localhost';`\
73-`  user : Pchar= 'myusername';`\
74-`  passwd: Pchar = 'mypassword';`
93+``` pascal
94+const
95+ host : Pchar= 'localhost';
96+ user : Pchar= 'myusername';
97+ passwd: Pchar = 'mypassword';
98+```
7599
76100Het kan zijn dat je geen verbinding kunt maken met behulp de mysql_connect() call, en je de mysql_real_connect() call moet gebruiken die meer parameters heeft. Om de zaak nog wat gecompliceerder te maken is het aantal parameters gewijzigd van versie 3 (daar waren het er 7) naar versie 4 (waar het er 8 zijn). Voordat je mysql_real_connect kunt aanroepen moet je waarschijnlijk mysql_init() aanroepen, die niet is opgenomen in de originele mysql.pp maar wel in mysql_v4.pp.
77101
78102Dus de code om verbinding te maken met de database is:
79103
80-`{ a few extra variables}`\
81-`var`\
82-`  alloc : PMYSQL;`\
83-` `\
84-`{main program fragment}`\
85-` `\
86-`begin`\
87-` if paramcount=1 then`\
88-`   begin`\
89-`   Dummy:=Paramstr(1)+#0;`\
90-`   DataBase:=@Dummy[1];`\
91-`   end;`\
92-` `\
93-`Writeln ('Allocating Space...');`\
94-` alloc := mysql_init(PMYSQL(@qmysql));`\
95-` Write ('Connecting to MySQL...');`\
96-` sock :=  mysql_real_connect(alloc, host, user, passwd, database, 0, nil, 0);`\
97-` if sock=Nil then`\
98-`   begin`\
99-`   Writeln (stderr,'Couldn''t connect to MySQL.');`\
100-`   Writeln (stderr, 'Error was: ', mysql_error(@qmysql));`\
101-`   halt(1);`\
102-`   end;`\
103-` Writeln ('Done.');`\
104-` Writeln ('Connection data:');`\
105-`{$ifdef Unix}`\
106-` writeln ('Mysql_port      : ',mysql_port);`\
107-` writeln ('Mysql_unix_port : ',mysql_unix_port);`\
108-`{$endif}`\
109-` writeln ('Host info       : ',mysql_get_host_info(sock));`\
110-` writeln ('Server info     : ',mysql_stat(sock));`\
111-` writeln ('Client info     : ',mysql_get_client_info);`\
112-` `\
113-` Writeln ('Selecting Database ',DataBase,'...');`\
114-` if mysql_select_db(sock,DataBase) < 0 then`\
115-`   begin`\
116-`   Writeln (stderr,'Couldn''t select database ',Database);`\
117-`   Writeln (stderr,mysql_error(sock));`\
118-`   halt (1);`\
119-`   end;`\
120-`{... as original contents of testdb.pp}`
104+``` pascal
105+{ a few extra variables}
106+var
107+ alloc : PMYSQL;
108+
109+{main program fragment}
110+
111+begin
112+ if paramcount=1 then
113+ begin
114+ Dummy:=Paramstr(1)+#0;
115+ DataBase:=@Dummy[1];
116+ end;
117+
118+Writeln ('Allocating Space...');
119+ alloc := mysql_init(PMYSQL(@qmysql));
120+ Write ('Connecting to MySQL...');
121+ sock := mysql_real_connect(alloc, host, user, passwd, database, 0, nil, 0);
122+ if sock=Nil then
123+ begin
124+ Writeln (stderr,'Couldn''t connect to MySQL.');
125+ Writeln (stderr, 'Error was: ', mysql_error(@qmysql));
126+ halt(1);
127+ end;
128+ Writeln ('Done.');
129+ Writeln ('Connection data:');
130+{$ifdef Unix}
131+ writeln ('Mysql_port : ',mysql_port);
132+ writeln ('Mysql_unix_port : ',mysql_unix_port);
133+{$endif}
134+ writeln ('Host info : ',mysql_get_host_info(sock));
135+ writeln ('Server info : ',mysql_stat(sock));
136+ writeln ('Client info : ',mysql_get_client_info);
137+
138+ Writeln ('Selecting Database ',DataBase,'...');
139+ if mysql_select_db(sock,DataBase) < 0 then
140+ begin
141+ Writeln (stderr,'Couldn''t select database ',Database);
142+ Writeln (stderr,mysql_error(sock));
143+ halt (1);
144+ end;
145+{... as original contents of testdb.pp}
146+```
121147
122148OK, klaar om trydb.pp te compileren?
123149
124-` fpc trydb`
150+```text
151+ fpc trydb
152+```
125153
126154success! En voer het uit:
127155
128-` ./trydb`
156+```text
157+ ./trydb
158+```
129159
130160YES! Je hebt een lijst van FPC ontwikkelaars!
131161
132162Een paar mogelijke verbeteringen: Je kunt de invoer van de gebruiker gegevens en de SQL commando's interactief maken. Hiervoor worden variabelen gebruikt in plaats van constanten. Er kunnen SQL commando's ingevoerd worden totdat het commando 'quit' wordt ingevoerd. Zie de [[Lazarus Database Tutorial/TryDbpp|volledige listing]]. In deze versie worden de gebruikers gegevens in de console ingevoerd, waarna het programma in een loop komt waarbij SQL commando's kunnen worden ingevoerd en de resultaten worden getoond. Het programma eindigt als 'quit' wordt ingevoerd.
133163
134164Zie ook [[Lazarus Database Tutorial/SampleListing|Sample Console Listing]].
135165
136166### Verbinding met MySQL vanuit een Lazarus Programma
137167
138168Deze paragraaf toont hoe je Lazarus kunt verbinden met een MySQL database, en hoe je eenvoudige queries kunt laten uitvoeren met gebruik van de basic Lazarus componenten. Er worden geen data-aware componenten gebruikt, maar het laat de principes zien van het verbinden met de database.
139169
140170Maak een nieuw project in Lazarus:
141171
142-`Project -> New Project -> Application`
172+```text
173+Project -> New Project -> Application
174+```
143175
144176Kies voor Application en klik op Create. Er zal een nieuw automatisch gegenereerd Form worden getoond.
145177
146178Vergroot het form zodat het ongeveer 600 bij 800 is. Geef het form een nieuwe naam en wijzig de caption in 'TryMySQL'.
147179
148180Van de Standard Componenten tab plaats je drie Editboxes in de linker bovenhoek van het Form, en plaats direct boven elke editbox labels. Wijzig de captions en namen in 'Host' (en HostLabel,HostEdit), 'UserName' (en UserLabel, UserEdit) en 'Password' (met PasswdLabel en PasswdEdit). Je kunt natuurlijk ook gebruik maken van de LabelledEdit componenten van de Additional tab.
149181
150182Selecteer de Passwd Editbox en zoek de PasswordChar property: wijzig dit in * , zodat wanneer je hier een paswoord intypt de letters niet getoond worden maar een serie van *-en. Zorg er voor dat de Text properties van alle editbox-en leeg zijn.
151183
152184Onder deze editbox plaatsen we een button. Zet de Caption hiervan op 'Connect to server' en geef het de naam 'ConnectButton'.
153185
154186Daarna zetten we een tweetal Comboboxen op het form met daarboven een Label. Deze noemen we DatabaseComboBox (en DatabaseLabel) en TableComboBox (en TableLabel). Tussen beide comboboxen plaatsen we nog een button, Caption = Select Database, Name = SelectDBButton.
155187
156188Dan nog een Label, een Listbox (FieldLabel en FieldListbox) en een Button (Caption = Exit, Name = ExitButton)
157189
158190Plaats nu nog een Editbox en label aan de rechter bovenkant van je form. Wijzig het label in 'Enter SQL Command' en noem de Editbox CommandEdit. Daaronder plaats je een button, 'Send Query' (QueryButton).
159191
160192Plaats een grote Memo op het form genaamd 'Results' (ResultMemo) op de rechter onderkant, zodanig dat het het grootste deel van het form vult. Zet het ScrollBars property op ssAutoBoth zodat de scroll bars automatisch veschijnen als het memo wordt gevuld. Zet het WordWrap property op True.
161193
162194Plaats een Status Bar (van de Common Controls tab) aan de onderkant van het Form, en zet de SimpleText property op 'TryMySQL'.
163195
164196Een screenshot van het formulier kun je hier zien: [Mysql Example Screenshot](http://lazarus-ccr.sourceforge.net/kb/index.php/Image:Trymysql.png)
165197
166198Nu moeten we nog de code (een aantal event handlers) schrijven.
167199
168200De drie Editboxen aan de linker bovenkant worden gebruikt om de hostnaam, gebruikersnaam en het wachtwoord in te voeren. Wanneer deze zijn ingevuld kan er op de "Connect" button geklikt worden. De OnClick-event van deze button is gebaseerd op een deel van het FPC programma hierboven.
169201
170202Omdat we nu de antwoorden van de database server niet met Write of WriteLn kunnen tonen, zullen we deze in het Memo laten zien. Hiervoor is het wel noodzakelijk dat we deze resultaten omzetten naar strings. We maken hiervoor een methode van ons form die de strings in het memo plaatst.
171203
172-`procedure TtrymysqlForm1.ShowString (S : string);`\
173-`(* display a string in a Memo box *)`\
174-`begin`\
175-`  ResultsMemo.Lines.Add (S)`\
176-`end;`
204+``` pascal
205+procedure TtrymysqlForm1.ShowString (S : string);
206+(* display a string in a Memo box *)
207+begin
208+ ResultsMemo.Lines.Add (S)
209+end;
210+```
177211
178212Het OnClick-event van de ConnectButton wordt dan:
179213
180-`procedure TFormTryMySQL.ConnectButtonClick(Sender: TObject);`\
181-`var`\
182-`  databasenamesBuffer: PMYSQL_RES;`\
183-`  aDatabase: TMYSQL_ROW;`\
184-`begin`\
185-`  // Connect to server.`\
186-`  // Clear a previous connection.`\
187-`  if mySQLSock <> nil then begin`\
188-`    mysql_close(mySQLSock);`\
189-`    DatabaseComboBox.Clear;`\
190-`    DatabaseComboBoxChange(DatabaseComboBox);`\
191-`  end;`\
192-`  mySQLSock := mysql_connect(@mySQLq, PChar(HostEdit.Text),`\
193-`                             PChar(UserEdit.Text), PChar(PasswdEdit.Text));`\
194-`  if mySQLSock = nil then begin`\
195-`    ShowString('Connection to server failed.');`\
196-`    ShowString('Error was: '+ StrPas(mysql_error(@mySQLq)));`\
197-`  end else begin`\
198-`    StatusBar1.SimpleText := 'Connected to database server.';`\
199-`    ShowString('Host info       : ' + StrPas(mysql_get_host_info(mySQLSock)));`\
200-`    ShowString('Server info     : ' + StrPas(mysql_stat(mySQLSock)));`\
201-`    ShowString('Client info     : ' + Strpas(mysql_get_client_info));`\
202-`  {$ifdef Unix}`\
203-`    ShowString('Mysql_port      : '+ IntToStr(mysql_port));`\
204-`    ShowString('Mysql_unix_port : ' + StrPas(mysql_unix_port));`\
205-`  {$endif}`\
206-`    databasenamesBuffer := mysql_list_dbs(mySQLSock, nil);`\
207-`    try`\
208-`      // Add each database as a item to our DatabaseComboBox.`\
209-`      aDatabase := mysql_fetch_row(databasenamesBuffer);`\
210-`      while (aDatabase <> nil) do begin`\
211-`        DatabaseComboBox.Items.Add(aDatabase[0]);`\
212-`        adatabase := mysql_fetch_row(databasenamesBuffer);`\
213-`      end;`\
214-`    finally`\
215-`      // finally free the result.`\
216-`      mysql_free_result(databasenamesBuffer);`\
217-`    end;`\
218-`  end;`\
219-`end;`
214+``` pascal
215+procedure TFormTryMySQL.ConnectButtonClick(Sender: TObject);
216+var
217+ databasenamesBuffer: PMYSQL_RES;
218+ aDatabase: TMYSQL_ROW;
219+begin
220+ // Connect to server.
221+ // Clear a previous connection.
222+ if mySQLSock <> nil then begin
223+ mysql_close(mySQLSock);
224+ DatabaseComboBox.Clear;
225+ DatabaseComboBoxChange(DatabaseComboBox);
226+ end;
227+ mySQLSock := mysql_connect(@mySQLq, PChar(HostEdit.Text),
228+ PChar(UserEdit.Text), PChar(PasswdEdit.Text));
229+ if mySQLSock = nil then begin
230+ ShowString('Connection to server failed.');
231+ ShowString('Error was: '+ StrPas(mysql_error(@mySQLq)));
232+ end else begin
233+ StatusBar1.SimpleText := 'Connected to database server.';
234+ ShowString('Host info : ' + StrPas(mysql_get_host_info(mySQLSock)));
235+ ShowString('Server info : ' + StrPas(mysql_stat(mySQLSock)));
236+ ShowString('Client info : ' + Strpas(mysql_get_client_info));
237+ {$ifdef Unix}
238+ ShowString('Mysql_port : '+ IntToStr(mysql_port));
239+ ShowString('Mysql_unix_port : ' + StrPas(mysql_unix_port));
240+ {$endif}
241+ databasenamesBuffer := mysql_list_dbs(mySQLSock, nil);
242+ try
243+ // Add each database as a item to our DatabaseComboBox.
244+ aDatabase := mysql_fetch_row(databasenamesBuffer);
245+ while (aDatabase <> nil) do begin
246+ DatabaseComboBox.Items.Add(aDatabase[0]);
247+ adatabase := mysql_fetch_row(databasenamesBuffer);
248+ end;
249+ finally
250+ // finally free the result.
251+ mysql_free_result(databasenamesBuffer);
252+ end;
253+ end;
254+end;
255+```
220256
221257Als dit succesvol is geweest, zal de DatabaseComboBox gevuld zijn met de op de server bekende databases. De SelectDBButton wordt dan geactiveerd zodra er een database is geselecteerd in de ComboBox. Een druk op de SelectDBButton zal de TableComboBox vullen met de in de database aanwezige tabellen. Bovendien zal dan ook de OpenQueryButton 'enabled' worden. Een en ander gebeurt in de volgende code:
222258
223-`procedure TFormTryMySQL.SelectDBButtonClick(Sender: TObject);`\
224-`var`\
225-`  tablenamesBuffer: PMYSQL_RES;`\
226-`  aTable: TMYSQL_ROW;`\
227-`begin`\
228-`  // Connect to the selected database`\
229-`  if DatabaseComboBox.ItemIndex <> -1 then begin // not really necessary but ...`\
230-`    ShowString('Now selecting database : ' + DatabaseComboBox.Text);`\
231-`    if mysql_select_db(mySQLSock, PChar(DatabaseComboBox.Text)) < 0 then begin`\
232-`      // if we failed, the QueryButton must not be enabled. :)`\
233-`      OpenQueryButton.Enabled := False;`\
234-`      // Show what went wrong.`\
235-`      ShowString('Couldn''t select database '+ DatabaseComboBox.Text);`\
236-`      ShowString(mysql_error(mySQLSock));`\
237-`    end else begin`\
238-`      // We got connected to the database, so lets get a list of tables.`\
239-`      TableComboBox.Clear;`\
240-`      tablenamesBuffer := mysql_list_tables(mySQLSock, nil);`\
241-`      aTable := mysql_fetch_row(tablenamesBuffer);`\
242-`      // Off course "SHOW TABLES" could work as well.`\
243-`      while (aTable <> nil) do begin`\
244-`        TableComboBox.Items.Add(aTable[0]);`\
245-`        aTable := mysql_fetch_row(tablenamesBuffer);`\
246-`      end;`\
247-`      mysql_free_result(tablenamesBuffer);`\
248-`      OpenQueryButton.Enabled := True;`\
249-`    end;`\
250-`  end else begin`\
251-`    ShowMessage('Please select a database in the `*`database`*`combobox.');`\
252-`  end;`\
253-`end;`
259+``` pascal
260+procedure TFormTryMySQL.SelectDBButtonClick(Sender: TObject);
261+var
262+ tablenamesBuffer: PMYSQL_RES;
263+ aTable: TMYSQL_ROW;
264+begin
265+ // Connect to the selected database
266+ if DatabaseComboBox.ItemIndex <> -1 then begin // not really necessary but ...
267+ ShowString('Now selecting database : ' + DatabaseComboBox.Text);
268+ if mysql_select_db(mySQLSock, PChar(DatabaseComboBox.Text)) < 0 then begin
269+ // if we failed, the QueryButton must not be enabled. :)
270+ OpenQueryButton.Enabled := False;
271+ // Show what went wrong.
272+ ShowString('Couldn''t select database '+ DatabaseComboBox.Text);
273+ ShowString(mysql_error(mySQLSock));
274+ end else begin
275+ // We got connected to the database, so lets get a list of tables.
276+ TableComboBox.Clear;
277+ tablenamesBuffer := mysql_list_tables(mySQLSock, nil);
278+ aTable := mysql_fetch_row(tablenamesBuffer);
279+ // Off course "SHOW TABLES" could work as well.
280+ while (aTable <> nil) do begin
281+ TableComboBox.Items.Add(aTable[0]);
282+ aTable := mysql_fetch_row(tablenamesBuffer);
283+ end;
284+ mysql_free_result(tablenamesBuffer);
285+ OpenQueryButton.Enabled := True;
286+ end;
287+ end else begin
288+ ShowMessage('Please select a database in the databasecombobox.');
289+ end;
290+end;
291+```
254292
255293In de EditBox rechts bovenin het form kan dan een SQL commando worden ingevoerd (zonder afsluitende punt-komma). Als er op de OpenQuery button geklikt wordt, wordt het commando naar de server gestuurd en als er data te tonen is, zal dat in een tweede form getoond worden.
256294
257295Ook het OnClick-event van de OpenQuery-button is gebaseerd op de code van de FPC versie hierboven.
258296
259297Het OnClick-event voor de OpenQuery-button is als volgt:
260298
261-`procedure TFormTryMySQL.OpenQueryButtonClick(Sender: TObject);`\
262-`var`\
263-`  I: Integer;`\
264-`  tableBuffer: PMYSQL_RES;`\
265-`  recordBuffer: TMYSQL_ROW;`\
266-`  aColumn: TListColumn;`\
267-`begin`\
268-`// An example of how to work with the returned data.`\
269-`  StatusBar1.SimpleText := 'Executing query: ' + CommandEdit.Text;`\
270-`  ShowString('Executing query: ' + CommandEdit.Text);`\
271-`  ShowQueryForm := TShowQueryForm.Create(nil);`\
272-`  try`\
273-`    Screen.Cursor := crHourGlass;`\
274-`    try`\
275-`      if (mysql_query(mySQLSock, pChar(CommandEdit.Text)) < 0) then begin`\
276-`        ShowString('Query failed '+ StrPas(mysql_error(mySQLSock)));`\
277-`        Raise(Exception.Create('Query failed.'));`\
278-`      end else begin`\
279-`        tableBuffer := mysql_store_result(mySQLSock);`\
280-`        // mysql_store_result will return nil if there was nothing to store.`\
281-`        if tableBuffer <> nil then begin`\
282-`          ShowString('Number of records returned  : ' +`\
283-`                                        IntToStr(mysql_num_rows(tableBuffer)));`\
284-`          ShowString('Number of fields per record : ' +`\
285-`                                      IntToStr(mysql_num_fields(tableBuffer)));`\
286-`          try`\
287-`            ShowQueryForm.ListView1.Columns.Clear;`\
288-`            // Now we are going to add a column for each field in the return set`\
289-`            // The caption of the columns we name after the fieldnames.`\
290-`            for I := 0 to pred(mysql_num_fields(tableBuffer)) do begin`\
291-`              aColumn := ShowQueryForm.ListView1.Columns.Add;`\
292-`              aColumn.Caption := mysql_fetch_field_direct(tableBuffer, I).name;`\
293-`            end;`\
294-`            // Let us see if the table contained data an ask for the first record`\
295-`            recordBuffer := mysql_fetch_row(tableBuffer);`\
296-`            while (recordBuffer <> nil) do begin`\
297-`              // We got some data lets add them to our view.`\
298-`              with ShowQueryForm.ListView1.Items.Add do begin`\
299-`                Caption := recordBuffer[0]; // This fills the first column`\
300-`                for I := 1 to pred(mysql_num_fields(tableBuffer)) do`\
301-`                  // Then we will add the other fields.`\
302-`                  SubItems.Add(recordBuffer[I]);`\
303-`              end;`\
304-`              recordBuffer := mysql_fetch_row(tableBuffer);`\
305-`            end; //while`\
306-`          finally`\
307-`            mysql_free_result(tableBuffer);`\
308-`          end;`\
309-`        end else begin`\
310-`          ShowString('Query didnot return any results.');`\
311-`        end;`\
312-`      end;`\
313-`    finally`\
314-`      Screen.Cursor := crDefault;`\
315-`    end;`\
316-`    ShowQueryForm.ShowModal;`\
317-`  finally`\
318-`    ShowQueryForm.Free;`\
319-`  end;`\
320-`end;`
299+``` pascal
300+procedure TFormTryMySQL.OpenQueryButtonClick(Sender: TObject);
301+var
302+ I: Integer;
303+ tableBuffer: PMYSQL_RES;
304+ recordBuffer: TMYSQL_ROW;
305+ aColumn: TListColumn;
306+begin
307+// An example of how to work with the returned data.
308+ StatusBar1.SimpleText := 'Executing query: ' + CommandEdit.Text;
309+ ShowString('Executing query: ' + CommandEdit.Text);
310+ ShowQueryForm := TShowQueryForm.Create(nil);
311+ try
312+ Screen.Cursor := crHourGlass;
313+ try
314+ if (mysql_query(mySQLSock, pChar(CommandEdit.Text)) < 0) then begin
315+ ShowString('Query failed '+ StrPas(mysql_error(mySQLSock)));
316+ Raise(Exception.Create('Query failed.'));
317+ end else begin
318+ tableBuffer := mysql_store_result(mySQLSock);
319+ // mysql_store_result will return nil if there was nothing to store.
320+ if tableBuffer <> nil then begin
321+ ShowString('Number of records returned : ' +
322+ IntToStr(mysql_num_rows(tableBuffer)));
323+ ShowString('Number of fields per record : ' +
324+ IntToStr(mysql_num_fields(tableBuffer)));
325+ try
326+ ShowQueryForm.ListView1.Columns.Clear;
327+ // Now we are going to add a column for each field in the return set
328+ // The caption of the columns we name after the fieldnames.
329+ for I := 0 to pred(mysql_num_fields(tableBuffer)) do begin
330+ aColumn := ShowQueryForm.ListView1.Columns.Add;
331+ aColumn.Caption := mysql_fetch_field_direct(tableBuffer, I).name;
332+ end;
333+ // Let us see if the table contained data an ask for the first record
334+ recordBuffer := mysql_fetch_row(tableBuffer);
335+ while (recordBuffer <> nil) do begin
336+ // We got some data lets add them to our view.
337+ with ShowQueryForm.ListView1.Items.Add do begin
338+ Caption := recordBuffer[0]; // This fills the first column
339+ for I := 1 to pred(mysql_num_fields(tableBuffer)) do
340+ // Then we will add the other fields.
341+ SubItems.Add(recordBuffer[I]);
342+ end;
343+ recordBuffer := mysql_fetch_row(tableBuffer);
344+ end; //while
345+ finally
346+ mysql_free_result(tableBuffer);
347+ end;
348+ end else begin
349+ ShowString('Query didnot return any results.');
350+ end;
351+ end;
352+ finally
353+ Screen.Cursor := crDefault;
354+ end;
355+ ShowQueryForm.ShowModal;
356+ finally
357+ ShowQueryForm.Free;
358+ end;
359+end;
360+```
321361
322362Er zijn nog een drietal andere event-handlers geschreven. Eén voor het OnClose-event van het form en voor de OnChange-events van beide ComboBoxen.
323363
324364In afwijking van het FPC programma, wordt het Lazarus programma niet afgebroken als er een fout optreedt. In plaats daarvan komt de controle weer terug bij het hoofd form (main form) en wordt de gelegenheid gegeven om het commando te verbeteren voordat het opnieuw wordt verstuurd naar de server. Het programma wordt afgesloten als op de Exit button wordt geklikt, hierbij wordt ook de verbinding met de MySQL server gesloten.
325365
326366OK! Sla je project op en klik op Run -\> Run
327367
328368#### Download MySQL Source Code
329369
330370Een volledige listing van het programma is hier te downloaden [Sample Source Code](http://prdownloads.sourceforge.net/lazarus-ccr/trymysql20050404.tar.gz?download) Er staat meer commentaar in de sources, dat de verschillende onderdelen toelicht.
331371
332372## Lazarus en Postgresql
333373
334374Wie schrijft mij?
335375
336376## Lazarus en SQLite
337377
338378door Luiz Américo
339379
340380### Introductie
341381
342382Er zijn twee TDataset afstammelingen die het mogelijk maken om SQLite2.x databases te benaderen. De eerste, de TSqlite class, is gedefinieerd in de SQLiteDataset unit. De tweede is gedefinieerd in de SQLiteds unit en is nieuwer en wordt bij de nieuwere fpc versie geïnstalleerd. De laatste heeft nog een paar voordelen boven de eerste versie, hij is sneller, maakt toevoegen, wijzigen en verwijderen mogelijk en kan deze updates automatisch door de database laten verwerken. De aanwijzigingen die hier gegeven worden gaan uit van de TSqliteDataset uit de unit sqliteds.pas. Het is zelfs zo dat de "oude" sqlitedataset.pas file onder de nieuwere versie van fpc (1.9.8) niet meer gecompileerd kan worden.
343383
344384### Benodigdheden
345385
346386- fpc 1.9.8
347387- sqliteds.pas (Haal deze eventueel van fpc/fcl/db/sqlite op de CVS-server)
348388- sqlite runtime library 2.8.15 of hoger (Haal deze van www.sqlite.org)
349389
350390**Voordat je een Lazarus project begint, controleer dan dat:**
351391
352392- de sqlite library te vinden is in het system PATH
353393- onder linux moet cmem als de eerste unit in de uses clause van het Main form vermeld worden
354394
355395### De grondbeginselen
356396
357397De sqlite package die bij de standaard lazarus installatie zie is gebaseerd op de oude sqlitedataset unit. Je kunt een package die gebruik maakt van de nieuwe unit [hier](http://www.geocities.com/camara_luiz/sqliteds.zip)downloaden.
358398
359399Tijdens het ontwerp moet je de volgende properties zetten:
360400
361401- FileName: pad naar de sqlite file \[verplicht\]
362402- TableName: de naam van de tabel die gebruikt wordt in het sql statement \[verplicht\]
363403- Sql: een SQL select statement \[optioneel\]
364404
365405**Een Table (Dataset) maken**
366406
367407Op dit moment is het niet mogelijk een tabel gedurende het programma ontwerp te maken dus is het noodzakelijk de tabel tijdens de uitvoering van het programma te maken als deze tenminste nog niet bestaat. Het beste moment hiervoor is in het OnCreate event van het "main" form.
368408
369409Het voorbeeld hieronder laat zien hoe je dit kunt doen. (dsTest is een instantie van TSqliteDataSet):
370410
371-` // Maake een tabel met alle door de TSqliteDataset ondersteunde veld typen`\
372-` with dsTest do`\
373-` begin`\
374-`   if not TableExists then begin`\
375-`     with FieldDefs do begin`\
376-`       Clear;`\
377-`       Add('Integer',ftInteger);`\
378-`       Add('AutoInc',ftAutoInc);`\
379-`       Add('String',ftString);`\
380-`       Add('Memo',ftMemo);`\
381-`       Add('Bool',ftBoolean); `\
382-`       Add('Float',ftFloat);`\
383-`       Add('Word',ftWord);`\
384-`       Add('DateTime',ftDateTime);`\
385-`       Add('Date',ftDate);`\
386-`       Add('Time',ftTime);`\
387-`     end;`\
388-`     CreateTable; `\
389-`   end;`\
390-` end;`
411+``` pascal
412+ // Maake een tabel met alle door de TSqliteDataset ondersteunde veld typen
413+ with dsTest do
414+ begin
415+ if not TableExists then begin
416+ with FieldDefs do begin
417+ Clear;
418+ Add('Integer',ftInteger);
419+ Add('AutoInc',ftAutoInc);
420+ Add('String',ftString);
421+ Add('Memo',ftMemo);
422+ Add('Bool',ftBoolean);
423+ Add('Float',ftFloat);
424+ Add('Word',ftWord);
425+ Add('DateTime',ftDateTime);
426+ Add('Date',ftDate);
427+ Add('Time',ftTime);
428+ end;
429+ CreateTable;
430+ end;
431+ end;
432+```
391433
392434**Gegevens opvragen**
393435
394436Nadat de tabel is gemaakt, kun je deze benaderen met de Open method. Als het SQL property geen waarde heeft worden alle velden van alle records uit de tabel opgehaald, dus alsof
395437
396-` SQL:='Select * from TABLENAME'; `
438+``` pascal
439+ SQL:='Select * from TABLENAME';
440+```
397441
398442Maar het is natuurlijk ook mogelijk om een combinatie van velden op te vragen door het SQL property te zetten zoals:
399443
400-` SQL:='Select Float from TABLENAME';`\
401-` SQL:='Select String,Date,Word from TABLENAME';`
444+``` pascal
445+ SQL:='Select Float from TABLENAME';
446+ SQL:='Select String,Date,Word from TABLENAME';
447+```
402448
403449Onthoud dat de beschikbare velden en de volgorde van deze velden na het openen van de dataset bepaald worden door het opgegeven select statement. In boven genoemde voorbeelden zijn er dus respectievelijk 10, 1 en 3 velden beschikbaar.
404450
405451**Wijzigingen doorvoeren op de onderliggende database**
406452
407453Voor het opslaan van de wijzigingen in de onderliggende database is het noodzakelijk dat de tabel een Primary key heeft. Bijvoorbeeld een AutoInc veld.
408454
409455Als bijvoorbeeld het veld 'Integer' waarden bevat die altijd aanwezig en uniek zijn, dan kunnen na
410456
411-` FieldIndexName:='Integer';`
457+``` pascal
458+ FieldIndexName:='Integer';
459+```
412460
413461gegevens in de database file worden opgeslagen.
414462
415463Hiervoor kun je de ApplyUpdates method gebruiken.
416464
417465### Opmerkingen
418466
419467- Hoewel dit tijdens een test met 10000 records goed werkte, moet je er wel rekening mee houden dat de TSqliteDataset alle gegevens in het geheugen houdt. Dus haal alleen de noodzakelijke gegevens op.
420468- Een database file kan meerdere tabellen bevatten.
421469- Het is mogelijke meerdere datasets (met verschillende velden) te maken die dezelfde database tabel benaderen.
422470- Het is mogelijk om de data te filteren met behulp van een WHERE statement. Het sluiten en het weer openen vban een dataset (of het aanroepen van de RefetchData method) is ook mogelijk.
423471- Je kunt ook complexe SQL statements gebruiken waarin aliases en joins worden gebruikt. Het is in dit geval echter niet mogelijk om gegevens te wijzigen, ApplyUpdates werkt dus niet. Als je echter toch complexe queries wilt gebruiken en gegevens wilt kunnen wijzigen, dan mag je mij een mailtje sturen en ik zal je een paar hints geven over hoe je dat kunt doen.
424472- Als je gebruik maakt van een bestand die niet is aangemaakt met behulp van een TSqliteDataset zijn er een paar beperkingen. Niet alle velden worden dan juist gedetecteerd. De niet herkende veldtype worden als een string behandeld.
425473
426474Een algemeen voorbeeld kan gevonden worden in de fpc/fcl/sqlite CVS directory.
427475
428476Luiz Américo pascalive(at)bol(dot)com(dot)br
429477
430478## Lazarus en MSSQL
431479
432480Wie schrijft mij?
433481
434482## Lazarus and Interbase / Firebird
435483
436484Zie [[Install Packages]]. Op deze pagina vind je een klein voorbeeld en bijbehorende uitleg over het verbinding met een IB of FB server.
437485
438486## Lazarus en dBase
439487
440488Tony Maro
441489
442490Kijk ook eens naar de aanzet voor een [[Lazarus Tdbf Tutorial|TDbf Tutorial page]]
443491
444492FPC bevat een simpel database component die qua functionaliteit is te vergelijken met het TTable component van Delphi. Dit component ("TDbf", ([TDbf Website](http://tdbf.sourceforge.net/))) ondersteund een aantal basis handelingen met dBase files. Omdat het niet standaard wordt geïnstallleerd, zul je dit component dus zelf moeten doen. Je kunt het package vinden in de "lazarus/components/tdbf" directory. Na installatie van het package en een "rebuild" van je Lazarus IDE, vind je het component naast het TDatasource component in je componenten palette.
445493
446494Het voordeel van het TDbf component is dat er geen extra libraries nodig zijn, maar het is niet de beste keuze voor een grote database applicatie.
447495
448496Het gebruik van een TDbf component is erg eenvoudig. Plaats eenTDbf component op je form, vul het FilePathFull property met het pad naar de directory waar de bestanden staan, vul het TableName property met de naam van de tabel en verbind het met een TDatasource.
449497
450498Voor het echte werk zul je echter nog wel iets meer moeten doen. Als een tabel nog niet bestaat, zul je hem met behulp van je programma moeten aanmaken. Of er moet een compatibele tabellen maker zijn die ik niet ken.
451499
452500Als je een niet bestaande tabel probeert te openen zal er een error gegenereert worden. Je kunt tijdens runtime een tabel aanmaken als het pad (FilePathFull) en de naam (TableName) een waarde hebben.
453501
454502De volgende code maakt een tabel genaamd "dvds" om he dvd verzameling in te registreren. Dus plaats een TDbf component op je form in in het OnCreate event van je form plaats je de volgende code:
455503
456-`   Dbf1.FilePathFull = '/pad/naar/mijn/database';`\
457-`   Dbf1.TableName = 'dvds';`\
458-`   With Dbf1.FieldDefs do begin`\
459-`       Add('Name', ftString, 80, True);`\
460-`       Add('Description', ftMemo, 0, False);`\
461-`       Add('Rating', ftString, 5, False);`\
462-`   end;`\
463-`   Dbf1.CreateTable;`
504+``` pascal
505+ Dbf1.FilePathFull = '/pad/naar/mijn/database';
506+ Dbf1.TableName = 'dvds';
507+ With Dbf1.FieldDefs do begin
508+ Add('Name', ftString, 80, True);
509+ Add('Description', ftMemo, 0, False);
510+ Add('Rating', ftString, 5, False);
511+ end;
512+ Dbf1.CreateTable;
513+```
464514
465515Nadat deze code is uitgevoerd is er een bestand "dvds.dbf" aangemaakt. Hierna kun je met behulp van alle data aware componenten, die via een DataSource aan het TDbf component zijn verbonden, de gegevens in de tabel eenvoudig benaderen en wijzigen.
466516
467517### Het maken van een index
468518
469519Het toevoegen van een index wijkt een beetje of van de typische TTable. Het moet namelijk gedaan worden, nadat de tabel is geopend. Op deze wijze moeten ook de index opnieuw opgebouwd worden. Bijvoorbeeld:
470520
471-`   Dbf1.Exclusive := True;`\
472-`   Dbf1.Open;`\
473-`   Dbf1.AddIndex('dvdsname','Name',[ixPrimary, ixUnique, ixCaseInsensitive]);`\
474-`   Dbf1.AddIndex('rating.ndx', 'Rating', [ixCaseInsensitive]);`\
475-`   Dbf1.Close;`
521+``` pascal
522+ Dbf1.Exclusive := True;
523+ Dbf1.Open;
524+ Dbf1.AddIndex('dvdsname','Name',[ixPrimary, ixUnique, ixCaseInsensitive]);
525+ Dbf1.AddIndex('rating.ndx', 'Rating', [ixCaseInsensitive]);
526+ Dbf1.Close;
527+```
476528
477529De eerste (primaire) index wordt opgeslagen in een bestand "dvdsname.mdx" en de tweede index wordt opgeslagen in een bestand genaamd "rating.ndx". Omdat index opgeslagen worden in aparte bestanden moet je er dus voor zorgen dat je niet twee maal dezelfde naam gebruikt.
478530
479531Ik zal proberen om op een later moment een meer gedetaileerd voorbeeld toe te voegen, maar ik hoop dat dit de delphi programmeurs snel op weg helpt bij het gebruik van databases in Lazarus!
480532
481533## Vertalingen van deze pagina
482534
483535[[Lazarus Database Tutorial]] Het origineel.\
484536[[Lazarus Database Tutorial/es|Spaans]] door Eduardo Lopez (thanks! :)
485537
486538## Gerelateerde Links
487539
488540[[Databases|Creating Databases Applications with Lazarus using the DB-unit]]\
489541[[MySQLDatabases|Creating a database application using MySQL]]\
490542[[Zeos tutorial|Creating a database application using the Zeos components]]
491543
492544---
493545*From the Free Pascal wiki, page "Lazarus Database Tutorial/nl", as it stood on 2011-08-03 after a change by Chronos, 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).*
494546Category: Databases/nl

Back to history