GG.AiM
Pe lista neagra
Inregistrat: acum 12 ani
Postari: 155
|
|
Notiuni introductive privind accesarea unei baze de date MYSQL din limbajul C
Acest tutorial presupune ca folositi sistemul de operare Linux (desi exemplele ar trebui sa se compileze si pe Windows). Mai presupun si ca server-ul MYSQL este instalat si, de asemenea, ca libraria client (utilizata pentru a scrie programe client care sa acceseze serverul) este instalata Tutorialul se adreseaza incepatorilor.
A. Pornirea si oprirea server-ului MYSQL Inainte de a accesa o baza de date MYSQL trebuie, evident, sa pornim serverul mysql.
Deschideti o console si executati:
%> sudo /etc/init.d/mysql start Password: xxxxx * Starting MySQL database server mysqld [ OK ] * Checking for corrupt, not cleanly closed and upgrade needing tables.
Inlocuiti "xxxxx" cu parola de root
Oprirea server-ului MYSQL: sudo /etc/init.d/mysql stop * Stopping MySQL database server mysqld [ OK ]
Verificarea daca server-ul MYSQL este pornit: %> sudo mysqladmin -p ping Password: Enter password: mysqld is alive
B. Api-ul client pentru MYSQL (in limbajul C)
Functii importante:
const char *mysql_get_client_info(void) Returneaza un string care reprezinta versiunea librariei client
MYSQL *mysql_init(MYSQL *mysql) Initializeaza un obiect MYSQL ce va fi folosit ulterior pentru conexiunea la server. Daca parametrul "mysql" este NULL, atunci se aloca un nou obiect MYSQL inainte de initializare si se intoarce un pointer la el Daca parametrul "mysql" nu este NULL, atunci obiectul pasat se reinitializeaza si se intoarce un pointer la acelasi obiect
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag) Aceasta este functia utilizata in programul client pentru conectarea la serverul MYSQL mysql - pointer la un obiect MYSQL, obtinut in urma unui apel al functiei mysql_init() host - un sir care contine adresa server-ului (hostname sau IP). Daca host contine sirul "localhost" sau este NULL, se presupune ca programul client si server-ul se afla pe aceeasi masina user - un sir de caractere care contine username-ul folosit pentru conectarea la server. Daca este NULL sau contine "", se presupune ca user-ul este cel curent passwd - parola folosita de "user" pentru conectarea la server db - numele bazei de date care va fi folosita in mod implicit port - daca nu este 0, specifica portul pe care clientul va incerca sa il foloseasca pentru a se conecta la server unix_socket - daca nu este NULL, specifica socket-ul (unix domain) sau pipe-ul folosit pentru comunicarea intre server si client client_flag - folosit pentru a seta diverse flag-uri, de exemplu daca pachetele transferate intre client si server vor fi comprimate (folosind Zlib), sau daca se foloseste SSL Functia intoarce un pointer catre un obiect MYSQL care va fi folosit ca un "handle" pentru comunicatia viitoare intre client si server. Daca functia esueaza se intoarce NULL
int mysql_query(MYSQL *mysql, const char *stmt_str) Functia este folosita de catre client pentru interogarea bazei de date mysql - un obiect MYSQL valid obtinut in urma unui apel mysql_real_connect care a reusit stmt_str - un string care reprezinta interogarea SQL ce va fi transmisa server-ului pentru a fi executata pe o baza de date. Se pot specifica mai multe "statement-uri" SQL separate prin caracterul ';' Daca interogarea a reusit se intoarce 0, altfel se intoarce o valoare diferita de 0
MYSQL_RES *mysql_store_result(MYSQL *mysql) Dupa apelul mysql_query() sau mysql_real_query() trebuie apelata functia mysql_store_result(). Aceasta intoarce un pointer la un obiect MYSQL_RES, care va fi folosit pentru extragerea rezultatului interogarii Se intoarce NULL daca functia esueaza
unsigned int mysql_num_fields(MYSQL_RES *result) Returneaza numarul de coloane returnat in urma unui apel mysql_store_result() result - este un pointer catre un obiect MYSQL_RES, intors de exemplu de catre functia mysql_store_result()
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result) Extrage urmatoarea linie din set-ul resultat in urma executiei unei interogari SQL result - un pointer la un obiect MYSQL_RES obtinut de exemplu in urma executiei unui apel mysql_store_result() Functie intoarce o structura de tip MYSQL_ROW folosita pentru a accesa urmatoare linie a setului. Se intoarce NULL daca am ajuns la sfarsitul setului
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result) Functia este utilizata pentru a obtine informatii despre o coloana apartinant unui set rezultat in urma executiei unei interogari SQL result - un pointer la un obiect MYSQL_RES obtinut de exemplu in urma executiei unui apel mysql_store_result() Functie intoarce o structura de tip MYSQL_FIELD folosita pentru a accesa informatii despre o coloana din set. Functia intoarce NULL cand s-au parcurs deja toate coloanele setului
void mysql_free_result(MYSQL_RES *result) Dezaloca resursele asociate unui obiect MYSQL_RES result - un pointer la un obiect MYSQL_RES obtinut de exemplu in urma executiei unui apel mysql_store_result()
void mysql_close(MYSQL *mysql) Inchide conexiunea catre server mysql - un obiect de tip MYSQL folosit pentru comunicatia intre client si server (obtinut, de exemplu, in urma unui apel mysql_real_connect())
Bun, aceste sunt functiile principale ale API-ului. Sa vedem cum sunt folosite in programe practice.
C) Exemple de programe client Asigurati-va ca sever-ul MYSQL este pornit inainte sa executati programele demonstrative ce vor urma
Programele client trebuie sa include urmatoarele header-e: "my_global.h" si "mysql.h"
C.1) Aflarea versiunii clientului
Code:
/* versiune_client.c */ #include <stdio.h> #include <stdlib.h> #include <my_global.h> #include <mysql.h>
int main() { fprintf(stdout, "Versiunea clientului este %s\n", mysql_get_client_info()); return EXIT_SUCCESS; }
Explicatii
mysql_get_client_info() ->returneaza un string ce indica versiunea librariei client
Compilare: %> gcc versiune_client.c -o versiune_client `mysql_config --cflags --libs`
Executie: %> chmod +x versiune_client %> ./versiune_client Versiunea clientului este 5.0.38
C.2) Crearea unei baze de date Vom crea o baza de date pe care o vom denumi "info_studenti". Ea va fi folosita pentru a tine informatii despre studentii participanti la un curs
Code:
/* creare_bd.c */ #include <stdio.h> #include <stdlib.h> #include <my_global.h> #include <mysql.h>
int main() { MYSQL *conn; conn = mysql_init(NULL);
if (conn == NULL) { fprintf(stderr, "Eroare %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; }
if (mysql_real_connect(conn, "localhost", "username", "parola", NULL, 0, NULL, 0) == NULL) { fprintf(stderr, "Eroare la conexiune catre server %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; }
if (mysql_query(conn, "create database info_studenti" != 0) { fprintf(stderr,"Error %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; }
fprintf(stdout, "Am create baza de date info_studenti\n"; mysql_close(conn); return EXIT_SUCCESS; }
Explicatii:
conn = mysql_init(NULL); -> initializez conn pentru conexiunea ulterioara catre baza de date
if (conn == NULL) { fprintf(stderr, "Eroare %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; } -> verific daca initializarea a reusit
if (mysql_real_connect(conn, "localhost", "username", "parola", NULL, 0, NULL, 0) == NULL) { fprintf(stderr, "Eroare la conexiune catres erver %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; } -> Ma conectez la server-ul MYSQL. In cazul meu, server-ul si clientul se afla pe aceeasi masina (am specificat localhost) Inlocuieste "username" si "parola" cu username-ul si parola ta
if (mysql_query(conn, "create database info_studenti" != 0) { fprintf(stderr,"Error %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; } -> Creez baza de date prin executia urmatoarei interogari SQL: "create database info_studenti"
mysql_close(conn); -> Inchide conexiunea catre server
Compilare: %> gcc creare_bd.c -o creare_bd `mysql_config --cflags --libs`
Executie: %> chmod +x creare_bd ./creare_bd Am create baza de date info_studenti
Nota: Daca vom mai incerca sa executam inca o data programul, vom obtine urmatoarea eroare: %> ./creare_bd Error 1007: Can't create database 'info_studenti'; database exists Aceasta deoarece putem sa creem baza de date o singura data
Hai sa vedem acum ca baza de date chiar a fost creata.
Putem sa folosim utilitarul mysql pentru a inspecta bazele de date existente. Executa din consola:
%> mysql -u root -p
apoi introdu parola De la promptul mysql> executa: mysql> SHOW DATABASES;
Exemplu:
mysql -u root -p Enter password: -> introduceti parola pentru user-ul root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 15 Server version: 5.0.38-Ubuntu_0ubuntu1.4-log Ubuntu 7.04 distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | info_studenti | | mysql | | testdb11 | +--------------------+ 4 rows in set (0.00 sec)#include <stdio.h>
mysql> quit Bye
Nota: Nu uita caracterul ';' dupa ce executi SHOW DATABASES;
Bun, am creat o baza de date. Acum e cazul sa si populam acea baza de date cu un tabel si sa introducem niste date in acel tabel.
C3) Creearea unui tabel si introducerea de inregistrari Vom crea un tabel care se numeste "studenti", in baza de date "info_studenti". Tabelul va contine urmatoarele date despre studenti: - ID - Nume - Medie
Tabelul va fi creat folosind urmatoarea interogare SQL: CREATE TABLE studenti(id int not null primary key auto_increment, nume varchar(20), media double)"
Tabelul va avea un intreg identificat prin "id" ca cheie primara de tip auto_increment. Aceasta inseamna ca valoarea campului "id" va fi incrementata automat de fiecare data cand in tabel for fi introduse inregistrari. Campul "nume" va fi folosit pentru a tine numele studentului. Campul "media" e de tip double si va contine media anuala a studentului
Codul este urmatorul:
Code:
/*inserare_date.c*/ #include <stdio.h> #include <stdlib.h> #include <my_global.h> #include <mysql.h>
int main() {
MYSQL *conn;
conn = mysql_init(NULL); if (conn == NULL) { fprintf(stderr, "Eroare la initializare %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; } if (mysql_real_connect(conn, "localhost", "username", "parola", "info_studenti", 0, NULL, 0) == NULL) { fprintf(stderr, "Eroare la conexiune catre server %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; }
if (mysql_query(conn, "CREATE TABLE studenti(id int not null primary key auto_increment, nume varchar(20), media double)" != 0) { fprintf(stderr, "Nu pot crea tabelul \"studenti\" in baza de date \"info_studenti\""; return EXIT_FAILURE; }
mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Ion', 7.77)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Gheorghe', 8)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Maria', 9.50)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Vasile', 10)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Dumitru', 5)";
mysql_close(conn); return EXIT_SUCCESS; }
Explicatii:
if (mysql_real_connect(conn, "localhost", "username", "parola", "info_studenti", 0, NULL, 0) == NULL) { fprintf(stderr, "Eroare la conexiune catre server %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; } -> Ma conectez la server-ul MYSQL. In cazul meu, server-ul si clientul se afla pe aceeasi masina (am specificat localhost) Inlocuieste "username" si "parola" cu username-ul si parola ta. In apel se specifica ca baza de date implicita pe care se vor face urmatoarele operatii va fi "info_studenti"
if (mysql_query(conn, "CREATE TABLE studenti(id int not null primary key auto_increment, nume varchar(20), media double)" != 0) { fprintf(stderr, "Nu pot crea tabelul \"studenti\" in baza de date \"info_studenti\""; return EXIT_FAILURE; } -> Creez tabelul "studenti", asa cum am explicat inainte
mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Ion', 7.77)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Gheorghe', 8)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Maria', 9.50)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Vasile', 10)"; mysql_query(conn, "INSERT INTO studenti(nume, media) VALUES('Dumitru', 5)"; -> Inserez inregistrari in tabelul "studenti" nou creat
Compilare: %> gcc inserare_date.c -o inserare_date `mysql_config --cflags --libs`
Executie: %> chmod +x inserare_date %> ./inserare_date
OK, hai sa vedem acum ca intr-adevar am creat tabelul si am adaugat inregistrari in el. Ca de obicei, folosim utilitarul mysql
%> mysql -u root -p Enter password: -> introduceti parola pentru user-ul root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 29 Server version: 5.0.38-Ubuntu_0ubuntu1.4-log Ubuntu 7.04 distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> USE info_studenti; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A
Database changed mysql> SHOW TABLES; +-------------------------+ | Tables_in_info_studenti | +-------------------------+ | studenti | +-------------------------+ 1 row in set (0.00 sec)
mysql> SELECT * FROM studenti; +----+----------+-------+ | id | nume | media | +----+----------+-------+ | 1 | Ion | 7.77 | | 2 | Gheorghe | 8 | | 3 | Maria | 9.5 | | 4 | Vasile | 10 | | 5 | Dumitru | 5 | +----+----------+-------+ 5 rows in set (0.00 sec)
mysql> quit Bye
Explicatii: USE info_studenti; -> selecteaza baza de date pentru care vrem sa obtinem informatii SHOW TABLES; -> afiseaza toate tabelele continute in baza de date selectata SELECT * FROM studenti; -> afiseaza toate inregistrarile continute in tabelul "studenti"
Bun, am invatat cum se creeaza si cum se populeaza un tabel. Hai sa vedem cum se extrag inregistrarile din tabele.
C4) Extragerea de inregistrari dintr-un tabel Pana acum am executat statement-uri SQL care nu returnau nici un set rezultat (result-set). In cazul anumitor interogari (de exmplu SELECT) vom avea set-uri rezultate. In programul urmator vom extrage datele introduse in tabelul "studenti" si vom afisa si toate coloanele asociate setului rezultat.
Code:
/*extragere_date.c */ #include <stdio.h> #include <stdlib.h>
#include <my_global.h> #include <mysql.h>
int main(int argc, char **argv) { MYSQL *conn; MYSQL_RES *result; MYSQL_ROW row; int num_fields; MYSQL_FIELD *field; int i;
conn = mysql_init(NULL); if (conn == NULL) { fprintf(stderr, "Eroare la initializare %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; } if (mysql_real_connect(conn, "localhost", "username", "parola", "info_studenti", 0, NULL, 0) == NULL) { fprintf(stderr, "Eroare la conexiune catre server %u: %s\n", mysql_errno(conn), mysql_error(conn)); return EXIT_FAILURE; }
mysql_query(conn, "SELECT * FROM studenti"; result = mysql_store_result(conn);
if (result == NULL) { fprintf(stdout, "Nu am gasit nici o inregistrare \n"; return EXIT_SUCCESS; }
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) { for (i = 0; i < num_fields; i++) { if (i == 0) { while(field = mysql_fetch_field(result)) { printf("%s ", field->name); } printf("\n"; } printf("%s ", row[i] ? row[i] : "NULL"; } } printf("\n"; mysql_free_result(result); mysql_close(conn); return EXIT_SUCCESS; }
Explicatii:
mysql_query(conn, "SELECT * FROM studenti"; -> executam urmatoarea interogare pentru a obtine toate inregistrarile din tabelul "studenti": SELECT * FROM studenti
result = mysql_store_result(conn); -> apelam mysql_store_result() pentru a "stoca" rezultatul interogarii
num_fields = mysql_num_fields(result); -> num_fields va contine numarul de coloane asociat setului "res"
while ((row = mysql_fetch_row(result))) { .... } -> parcurgem setul rezultat in urma interogarii line cu linie
for (i = 0; i < num_fields; i++) { ... } -> pentru fiecare linie a setului parcurgem fiecare coloana
if (i == 0) { while(field = mysql_fetch_field(result)) { printf("%s ", field->name); } printf("\n"; } -> inainte de a afisa prima linie a setului, afisam numele tuturor coloanelor
printf("%s ", row ? row[i] : "NULL"; -> [i]afisam linia curenta a setului apoi continuam iteratia pana cand parcurgem toate liniile setului
Compilare: %> gcc extragere_date.c -o extragere_date `mysql_config --cflags --libs`
Executie: %> chmod +x extragere_date %> ./extragere_date id nume media 1 Ion 7.77 2 Gheorghe 8 3 Maria 9.5 4 Vasile 10 5 Dumitru 5
In continuare prezint o serie de comenzi utile ce pot fi incercate atat utilizand un utilitar gen mysql sau din cod, programatic, folosind exemplele de mai sus:
SHOW DATABASES; -> afiseaza totate bazele de date aflate pe server-ul MYSQL CREATE DATABASE baza_de_date; -> creeaza o noua baza de date avand numele baza_de_date USE baza_date; -> selecteaza baza de date cu numele baza_de_date. Toate operatiile ulterioare se vor face pe aceasta baza de date (pana cand bineinteles, selectam alta) SHOW TABLES; -> afiseaza numele tuturor tabelelor bazei de date selectate curent SHOW COLUMNS FROM nume_tabel; ->ofera informatii despre coloanele tabelului nume_tabe DROP_TABLE nume_tabel; -> sterge un tabel numit nume_tabel din baza de date curent selectata DROP_DATABASE nume_database; -> sterge baza de date numita nume_database
Exista multe alte comenzi, dar va trebui sa cititi help-ul pentru a le afla.
In continuare se prezinta un exemplu de utilizare al comenzilor invatate folosind utilitarul mysql:
%> mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 43 Server version: 5.0.38-Ubuntu_0ubuntu1.4-log Ubuntu 7.04 distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | testdb11 | +--------------------+ 3 rows in set (0.00 sec)
mysql> CREATE DATABASE baza_de_date; Query OK, 1 row affected (0.00 sec)
mysql> USE baza_de_date; Database changed
mysql> SHOW TABLES; Empty set (0.00 sec)
mysql> CREATE TABLE studenti(id int not null primary key auto_increment, nume varchar(20), media double); Query OK, 0 rows affected (0.01 sec)
mysql> SHOW TABLES; +------------------------+ | Tables_in_baza_de_date | +------------------------+ | studenti | +------------------------+ 1 row in set (0.00 sec)
mysql> SHOW COLUMNS FROM studenti; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | nume | varchar(20) | YES | | NULL | | | media | double | YES | | NULL | | +-------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
mysql> SELECT * FROM studenti; Empty set (0.00 sec)
mysql> INSERT INTO studenti(nume, media) VALUES('Ion', 7.77); Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM studenti; +----+------+-------+ | id | nume | media | +----+------+-------+ | 1 | Ion | 7.77 | +----+------+-------+ 1 row in set (0.00 sec)
mysql> DROP TABLE studenti; Query OK, 0 rows affected (0.01 sec)
mysql> SHOW TABLES; Empty set (0.00 sec)
mysql> DROP DATABASE baza_de_date; Query OK, 0 rows affected (0.00 sec)
mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | testdb11 | +--------------------+ 3 rows in set (0.00 sec)
mysql> quit Cam mare tutorialu ) [ nu este facut de mine tutorialul dar sper sa va ajuta ]
Succes
|
|