Jump to content
nedo

[c++] Conectare la un fisier mdb/accdb prind Direct ODBC

Recommended Posts

Tutorialul este scris de mine si implica doar conectarea si executarea unei comenzi de inserare momentan. In timp ce mai invat mai adaug.

Tutorialul l-am facut deoarece majoritatea chestiilor pe care le-am gasit pentru Direct ODBC au fost doar in c, nu si in c++.

Aviz, tutorialul este inspirat de aici, acela este doar pentru C

Mai jos avem codul, pe care il explicam dupa.

PS. Pentru a putea compila codul aveti nevoie sa adaugati libraria libodbc32.a, vine cu code blocks, nu stiu despre celelalte ide-uri.

Pentru ca programul sa se poate conecta aveti nevoie sa setati in odbcad32.exe(acesta se afla in c:/windows/system32) locatia bazei voastre de date access.


#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>

using namespace std;


int main(int argc, char* argv[])
{
char szDSN[256] = "Driver={Microsoft Access Driver (*.mdb)};DSN='';DBQ=C:\\BAZE DE DATE\\test.mdb;";
const char* DAM = "Direct ODBC";
HENV hEnv;
HDBC hDbc;

RETCODE rc;
// exemplu de comanda.
string testquery = "INSERT INTO Customers (IndicatorJudet, NumeClient, Adresa) VALUES ('Bc', 'test11124', 'STR PRINCIPALA NR 10');";
int iConnStrLength2Ptr;
char szConnStrOut[256];
unsigned char* query = (unsigned char*)testquery.c_str();
SQLCHAR chval1[128], chval2[128], colName[128];
HSTMT hStmt;
rc = SQLAllocEnv(&hEnv);
rc = SQLAllocConnect(hEnv, &hDbc);

rc = SQLDriverConnect(hDbc, NULL, (unsigned char*)szDSN,
SQL_NTS, (unsigned char*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc))
{
cout << DAM << ": succesfuly connected to database.\nData source name " << szConnStrOut << endl;
// printam query-ul pe care il folosim
cout << DAM << " SQL Query: " << query << endl;
rc = SQLAllocStmt(hDbc,&hStmt);
rc = SQLPrepare(hStmt, query, SQL_NTS);
rc = SQLExecute(hStmt);
if(SQL_SUCCEEDED(rc))
{
cout << DAM << ": statement executed succesfuly\n";
}
else
{
cout << DAM << ": statement not executed\n";
}
}
else
{
cout << DAM << ": could not connect to " << szDSN << endl;
}

/* Disconnect and free up allocated handles */
SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

cout << DAM << ": Cleanup... done\n";

return 0;
}

Partea I: Variabilele necesare.

sdDSN tine numele driverului folosit, si locatia fisierului nostru mdb la care ne conectam, iar DAM defineste modul de conectare.


char szDSN[256] = "Driver={Microsoft Access Driver (*.mdb)};DSN='';DBQ=C:\\BAZE DE DATE\\test.mdb;";
const char* DAM = "Direct ODBC";

HENV va tine handle-ul mediului(enviroment) in care se va face conexiunea, acesta este de fapt un pointer void. Adica un pointer catre o locatie care nu contine nici o data.

HDBC va tine handle-ul conexiuni, si este la fel ca si HENV

HSTMT tine handle-ul pentru declaratia(statement) noastra.


HENV hEnv;
HDBC hDbc;
HSTMT hStmt;

Retcode este o variabila declarata prin typedef, care are la baza de fapt un short, ea va tine raspunsul dat de functiile sql pe care le vom executa.


RETCODE rc

iConnStrLengh2Ptr este un pointer de tip int catre o locatie din memorie unde va fi tinut numarul de caractere care este returnat de catre functie

szConnStrOut va tine outputul returnat de catre functie. El este folosit ca un pointer.


int iConnStrLength2Ptr;
char szConnStrOut[256];

Aici era o mica problema, deoarece exemplu de pe msdn nu putea fi compilat in c++.

Pentru a putea folosi un string normal trebuie sa face un cast, sa aruncam, stringul sub forma de pointer unsigned char pentru a putea fi folosit de query.

In query este tinuta de fapt comanda noastra sql ce va fi executata, in cazul nostru un insert.

tempquery va tine declaratia noastra temporara. Daca spre exemplu trebuie sa luam datele din mai multe locatii/variabile, acestea pot fi adunate in tempquery si abea apoi utilizata de query.


string tempquery;
unsigned char* query = (unsigned char*)tempquery.c_str();

Partea II: Cursul programului.

a.Intai alocam un mediu pentru conexiunea noastra prin intermediul functiei "SQLAllocEnv(&hEnv)", Aceasta ia referinta pointerului hEnv, si returneaza o variabila de tip RETCODE, in cazul nostru "rc"

b. Alocam conexiunea cu ajutorul SQLAllocConnect(hEnv, &hDbc), are nevoie de 2 parametri, hEnv si referinta la pointeru hDbc. Si aceasta functie returneaza tot o variabila de tip RETCODE, tot "rc" folosim si aici.

c. Ne conectam la driverul nostru si anume "Direct ODBC", cu ajutorul functiei

 
"SQLDriverConnect(hDbc, NULL, (unsigned char*)szDSN,
SQL_NTS, (unsigned char*)szConnStrOut,
255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT)"

Parametri necesari:

handle-ul conexiuni hDbc

handle-ul ferestrei mama, in cazul nostru este NULL deoarece nu vrem sa trimitem acest handle(nu este obligatoriu sa il trimitem)

szDSN care este folosit printr-un cast, care spune functiei numele driverului si locatia bazei noastre de date.

SQL_NTS se refera la un string terminat printr-un null character.

szConnStrOut la fel ca si szDSN prin care specificam functiei tipul conexiuni(direct connect)

255 este lungimea bufferului in care va fi tinut outputul functiei, care va fi salvat in szConnStrOut

iConnStrLength2Ptr este pointerul catre bufferul unde va fi salvat outputul, este folosit ca referinta(&)

SQL_DRIVER_NOPROMPT indica functiei ca nu mai are nevoie sa ceara alte informatii pentru conexiune. Acest ultim parametru poate avea parametrul nostru sau oricare din urmatorii parametri "SQL_DRIVER_PROMPT, SQL_DRIVER_COMPLETE, SQL_DRIVER_COMPLETE_REQUIRED".

Functia returneaza din nou o variabila de tip RETCODE ->rc

Verificam daca conexiunea a reusit prin :

"if(SQL_SUCCEEDED(rc))"

Daca functia s-a executat cu success afisam acest lucru prin:


cout << DAM << " succesfuly connected to database. Data source name " << szConnStrOut;

Alocam declaratia(statement) noastra.

Are nevoie de handle-ul conexiuni si referinta la handle-ul declaratiei.

Returneaza din nou un RETCODE


rc = SQLAllocStmt(hDbc,&hStmt);

Pregatim declaratie, functia are nevoie de handle-ul declaratiei, query-ul si lungimea query-ului, in cazul nostru specificam doar ca este terminat de un caracter null prin SQL_NTS


rc = SQLPrepare(hStmt, query, SQL_NTS);

Executam comanda, nu avem nevoie decat de handle-ul declaratiei care a fost pregatita in prealabil. Functia are si de aceasta data tot o variabila de tip RETCODE ca variabila de returnare.


rc = SQLExecute(hStmt);

Verificam din nou daca s-a executat cu succes comanda.


if(SQL_SUCCEEDED(rc))

Dupa ce am executat declaratia noastra facem curatenie

Intai ne deconectam de la driverul ODBC, apoi eliberam handle-ul conexiuni si al mediului in care s-a facut aceasta conexiune.


SQLDisconnect(hDbc);
SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

Partea III: Incheiere

Tutorialul nu este destinat unei aplicatii intregi deoarece este nevoie de mult mai multe vetificari priviind executarea comenzilor. Acesta este doar facut pentru a prezenta cum se poate efectua o conexiune prind Direct ODBC in c++ lucru greu de gasit pe net(cel putin de mine).

Pentru referinte puteti folosi msdn-ul dar e mai bine sa cautati functiile individuale pe net deoarece pe msdn sunt mai greu de gasit si de inteles.

Daca observati greseli de orice fel postati sau trimiteti pm.

Edited by nedo
  • Upvote 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...