26286 total geeks with 3498 solutions
Recent challengers:
 Welcome, you are an anonymous user! [register] [login] Get a yourname@osix.net email address 

Articles

GEEK

User's box
Username:
Password:

Forgot password?
New account

Shoutbox
MaxMouse
It's Friday... That's good enough for me!
CodeX
non stop lolz here but thats soon to end thanks to uni, surely the rest of the world is going good?
stabat
how things are going guys? Here... boring...
CodeX
I must be going wrong on the password lengths then, as long as it was done on ECB
MaxMouse
lol... the key is in hex (MD5: of the string "doit" without the "'s) and is in lower case. Maybe i should have submitted this as a challenge!

Donate
Donate and help us fund new challenges
Donate!
Due Date: May 31
May Goal: $40.00
Gross: $0.00
Net Balance: $0.00
Left to go: $40.00
Contributors


News Feeds
The Register
Aha, I see you
switched on your
mobile Wi-Fi. YOU
FOOL!
What"s that Dell?
You"re out? HDS
punts pay-per-use
cloud storage
Spam and the
Byzantine Empire:
How Bitcoin REALLY
works
IBM gets ready to
push more UK and
Irish bods
overboard
Backup bods Veeam
quietly gobbling up
ever-greater market
share
LOHAN is GO!
Reg
spaceplane BLASTS
OFF on 14 September
Happy 23rd
birthday, Windows
3.0
Microsoft melds
SkyDrive Pro and
SharePoint
Yahoo! Oz! PAYS!
Punters! Pittance!
To! Search!
AMD"s three new
low-power chips
pose potent
challenge to Intel
Slashdot
Why We Should
Celebrate Snapchat
and Encourage
Ephemeral
Communication
Teens, Social
Media, and Privacy
Physicists Create
Quantum Link
Between Photons
That Don"t Exist At
the Same Time
Missile Test
Creates Huge
Expanding Halo of
Light Over Hawaii
3D Printers For
Peace Contest
Intel"s Linux
OpenGL Driver
Faster Than Apple"s
OS X Driver
Rough Roving:
Curiosity"s Wheels
Show Damage
Tesla Motors Repays
$465M Government
Loan 9 Years Early
Why the "Star Trek
Computer" Will Be
Open Source and
Apache Licensed
NYPD Detective
Accused of Hiring
Email Hackers
Article viewer

A Crash Course in Using the MySQL C API



Written by:belarm
Published by:Nightscript
Published on:2004-05-07 03:37:56
Topic:C
Search OSI about C.More articles by belarm.
 viewed 40475 times send this article printer friendly

Digg this!
    Rate this article :
A quick run-down of the bare minimum you need to connect to and query a MySQL database in C.

Using a MySQL database in C is not very complicated, but I know that when I was starting out on it, I could have used some example code with documentation. With that fact in mind, here's some code:

#include <mysql/mysql.h>
#include <stdio.h>
#include <string.h>

int main()
{
   MYSQL mysql;
   MYSQL_RES *res;
   MYSQL_ROW row;

   char query[80];
   mysql_init(&mysql);
   mysql_real_connect(&mysql,"some.host.com","ipaudit","letmein","audit",0,NULL,0);
   sprintf(query,"SELECT src,dst FROM ipaudit");
   mysql_real_query(&mysql,query,(unsigned int)strlen(query));
   res = mysql_use_result(&mysql);
   while(row = mysql_fetch_row(res))
    printf("%s %sn",row[0],row[1]);
   mysql_free_result(res);
   return 0;
}


And there you have it: a program that will connect to the audit database on some.host.com with username audit and password letmein, execute a query, and print out the results.

Let's start at the beginning, shall we?

#include <mysql/mysql.h>


Hopefully you get the gist of this line. I only highlight it to show you where the header file is located.

   MYSQL mysql;
   MYSQL_RES *res;
   MYSQL_ROW row;


MySQL has quite a few custom structs it uses; these are the three you'll probably see most often.
  • MYSQL: this is a structure to hold information about a unique MySQL connection. Any functions which involve interaction with the server expect one of these to be passed by reference.
  • MYSQL_RES: this is a structure for holding a result set from a query. They can grow to be quite large, depending on which method you use to fetch your results. More on that later.
  • MYSQL_ROW: this holds one row from a result set. It can be accessed as an array of character pointers (strings) as seen later in the program.


mysql_init(&mysql);


This function MUST be called on all MYSQL objects. The name pretty much says it all; just your basic initialization function.

mysql_real_connect(&mysql,"some.host.com","ipaudit","letmein","audit",0,NULL,0);


Ah, now the nitty-gritty. This is probably the longest prototype in the API, but it's really not that complicated...so long as you remember the order of arguments.
The function takes(in order):

  • A reference to a MYSQL object (the one to be used for the connection, obviously)
  • A const char * that specifies a hostname or IP to connect to. Passing nothing or NULL causes the function to default to "localhost"
  • A username to connect to the server with. Blank or NULL values cause the function to default to the user running the program
  • The user's password. You can have blank passwords in MySQL, in which case this can be NULL or ""
  • The default database for queries. If you specify one here (optional), all queries will be presumed to operate on this database, instead of you having to use the database.table format
  • Port, socket, and client flags. Passing 0 and NULL (you guessed it) cause the API to use the default values(3306,new connection, and 0, respectively).


So in our example code, we're connecting with ipaudit:letmein@some.host.com:3306, and chosing the audit database as the default.

Now, the moment you've all been waiting for: The Mighty Query

mysql_real_query(&mysql,query,(unsigned int)strlen(query));


Okay. Kind of anti-climatic, I know. The three paramaters here are very self-explanitory: MYSQL *db_connection,const char *query,unsigned int query_length (my compiler complains about the return type of strlen, hence the type cast). Note that the format of the query is exactly like every other client interface for SQL ever invented (except for TrollTech's rumored C++ interface, that is)

Once this command has been executed, the server executes your query and stores the results locally (on the server, that is). Your next task is to retrieve them:

res = mysql_use_result(&mysql);


This line points your MYSQL_RES variable at the result set from the query you just executed. The API allocates a bit of memory for it, but it does not actually pull any rows until you request them with mysql_fetch_row(). This uses very little RAM, but relies more on a good network connection.

Now, if your network connection sucks (or you just want faster access to the results within a loop), you should consider using mysql_store_result() instead. On the buggy network I have to use at work, the use of store_result has saved me countless headaches, simply because I only have to have a good connection long enough to send the result set, not send and parse it (yes, it gets that bad where I work).

Now, to use that very creatively named row variable:

while(row = mysql_fetch_row(res))


mysql_fetch_row() returns one row at a time from a result set, or NULL when there are no more rows in the set. An empty result set will return NULL on the first call (this is different than the behavior in the case of an error; see below for error checking). We assign the returned value to a MYSQL_ROW structure, and we can (at last) get our data.

printf("%s %sn",row[0],row[1]);


That's all there is to pulling the data. ROWs are accessed as arrays of character pointers, and MySQL is nice enough to order the elements in the same order you list fields in your SELECT statement. So, in the example above, row[0] is the src field of a row, and row[1] is the dst field. One caveat: all data is returned as strings in this model, so you'll learn to love string to integer conversions quickly.

Last but not least, we free the memory used by the result set:

   mysql_fetch_row(res);


This must be done before re-using the MYSQL_RES structure for another query. It's especially important if you use mysql_store_result().

To compile the application, you'll have to link it against the appropriate libraries. On GNU/Linux, this is usually done with the following command:

gcc sql_prog.c -o sql_prog -lz -lmysqlclient -L /usr/lib/mysql/


There you have it! Everything you need to know to use a SQL database remotely. As long as nothing goes wrong. Ever.

Knowing how likely that is, let me show you a couple of things you can do to catch errors:

if(!mysql_real_connect(....))
{
   printf("Error connecting to database: %sn",mysql_error(&mysql));
   //exit gracefully here...
}


mysql_real_connect() returns a pointer to a MYSQL structure (which you'll probably never use) or NULL in the case of an error (which you'll use a lot). Check the return value and then call mysql_error(&connection) to get a very detailed and helpful error message (No, that's not sarcasm).

You may also call mysql_error() after a function who's success you wish to check. This will return non-zero if an error occurred during the most recent API call (with some exceptions; but the exceptional functions usually provide the ability to check for a NULL return value in any case)

mysql_error() will also return errors from the database server, so if your mysql_real_query() call fails, you can get the same error message you'd likely get if you were connected through a command-line client.

That's about it for the basics. The MYSQL API is, in my opinion, pretty well thought out and has very good error checking built in. My only gripe is the _real_ in their function names, which is there for historical reasons so as not to deprecate old code.

You should definately check out MySQL.com's documentation, as well:



On a side note, this is my first public technical article. I look forward to hearing your comments and suggestions on this article, and encourage questions pertaining to it - I'll do my best to answer them here or in a future article

Did you like this article? There are hundreds more.

Comments:
aidan
2004-05-07 10:07:34
I think it's a great article. Something that will interest alot of people here.
Obscurity
2004-05-07 10:21:00
Yeah it is, it's a really good article. And I enjoyed it.
DeMoNiCoN
2004-05-10 05:30:37
I always like to see these "programming by example" type articles, nice job :)

I especially appreciate the work you put into it as to link to the MySQL documentation for the functions in the code.

Hrm.. This might just motivate me enough to write a wrapper class in some language or another..
bb
2004-05-10 16:07:15
nice article, i fixed up your wrapping problem - there was a large amount of whitespace within the code block. i'll slap the editors to ensure this doesnt happen again
belarm
2004-05-11 16:04:37
bb: thanks for the formatting fix. must have done something odd while copying & pasting it.

DeMoNiCoN: are you thinking of writing a wrapper for this API in particular?
DeMoNiCoN
2004-05-12 08:50:38
Yeah belarm, thinking of coding a nice wrapper for the MySQL API. It would probably be best in C++, but I personally dislike that language :)

Ah well, I'll figure something out.
belarm
2004-05-13 04:15:52
What's not to like about C++?
...on second thought, never mind; i don't want to have that argument :-)
IIRC, TrollTech is rumored to be working on just such a thing as part of the new version of qt
jake_null
2004-08-17 08:42:28
nice article, i've used it as a reference numerous times now.
belarm
2004-10-18 20:09:12
Glad to hear it, jake.
outlaw
2004-12-05 03:12:37
very nice, that example makes the somewhat heavy mysql manual a bit easier to understand.
DarkForce
2006-06-27 08:39:07
can anyone help me with putting data in any DB file...like MYSQL, MS Access...any DB...I know the theory of DBs...I can get used to any of the DBs(programming that is)...am a quick learner....I just need to pass and save values in a DB using just C...rest is upto the DB admin!!!
Anonymous
2006-09-15 14:30:23
Check the code example under "Last but not least, we free the memory used by the result set:"

mysql_fetch_row(res);

I believe it should be

mysql_free_result(res);
Anonymous
2007-05-16 09:25:57
I tried with the code given by you. I got errors like as shown below
connectivity.c: undefined reference to `mysql_init'
/tmp/ccNgXB5h.o(.text+0x55):connectivity.c: undefined reference to `mysql_real_connect'
/tmp/ccNgXB5h.o(.text+0xa5):connectivity.c: undefined reference to `mysql_real_query'
/tmp/ccNgXB5h.o(.text+0xb7):connectivity.c: undefined reference to `mysql_use_result'
/tmp/ccNgXB5h.o(.text+0xe9):connectivity.c: undefined reference to `mysql_fetch_row'
/tmp/ccNgXB5h.o(.text+0x100):connectivity.c: undefined reference to `mysql_free_result'


Can any one help me.

Thank you in advance


Anonymous
2007-06-01 05:33:16
try with (i was getting the same message like you)

gcc -o test -L/usr/lib/mysql -lmysqlclient test.c

src: http://lists.mysql.com/mysql/200178
Anonymous
2007-07-01 17:40:40
or you can use "gcc -lz `mysql_config --libs --include`" to have it figure out where things out for you. This is a great article.
Anonymous
2008-12-04 10:17:58
Nice Article
Anonymous
2009-03-26 11:49:13
this article is not well defined
Anonymous
2009-03-26 11:51:23
this code requires dependency; i think mysql lib;
where are those things?
Anonymous
2009-03-26 11:55:25
yasin altaf

afaque ahemed
Anonymous
2009-03-26 13:17:21
session timeout ?
Anonymous
2009-03-26 13:55:13
registeration is really fast and we send you no spam
Anonymous
2009-04-08 14:32:37
idiot
Anonymous
2009-04-08 14:33:59
mysql_use_result
Anonymous
2009-06-17 12:23:38
thanks, this helped me get started with mysql C API very fast. I find the API to be remarkably sane :)
ObatAsamUrat
2011-06-16 07:44:05
Is fantastic blog site much. Remember to preserve modernizing your blog post. Perhaps it can be Christmas time time currently, Let me even now comply with your blog . My spouse and i figured out tons by you. Satisfied trip along with The new year brand-new calendar year!
kaos distro
Anonymous
2011-06-20 01:34:42
Thank you very much for this concise example! I was able to extend it to work with the Eventum ticketing system and provide our customers with a front end to check on job status.
Anonymously add a comment: (or register here)
(registration is really fast and we send you no spam)
BB Code is enabled.
Captcha Number:


Blogs: (People who have posted blogs on this subject..)
amisauv
Creating a Lexical Analyzer in C on Tue 9th Dec 11am
#include<stdio.h> #include<string.h> #include<conio.h> #include<ctype.h> /*************************************** ************************* Functions prototype. **************************************** *************************/ void Open_File(
amisauv
Controling digital circuit through computer on Tue 9th Dec 10am
this code access the lpt port.here only 4 of the total 8 pins are used but can be modified for full 8 pins.it has a complete GUI with mouse & keyboard interactive control panel.works well in win98, but not in winxp. #include<stdio.h> #include<conio.
amisauv
/* Computerised Electrical Equipment Control */ /* PC BASED DEVICE CONTROLLER * on Tue 9th Dec 10am
#include<stdio.h> #include<conio.h> #include<dos.h> void main() { void tone(void); int p=0x0378; char ex={"Created By Mrc"}; int j; char ex1={"For Further Details & Improvements"}; int k; char ex2={"Contact : E-mail : anbudan
amisauv
Calendar Program on Tue 9th Dec 10am
This program prints Weekdays of specified date. It even prints calendar of a given year too. /*Ccalendar library*/ #include<stdio.h> #include<string.h> #include<conio.h> int getNumberOfDays(int month,int year) { switch(month) { case
amisauv
Calculator: on Tue 9th Dec 10am
#include"graphics.h" #include"dos.h" #include"stdio.h" #include"math.h" union REGS i,o; char text={ "7","8","9","*","4","5","6","/","1","2", "3","+","0","00",".","-","M","M+", "M-","+/-","MR","MC","x^2","sr","OFF","A C","CE","="}; int s=0,k=0,pass
amisauv
INFECTED CODES WRITTEN IN C\C++ on Tue 9th Dec 10am
This is a simple code that changes system time and date. It is written using c/c++ but can be easily converted to java. #include "stdio.h" #include "process.h" #include "dos.h" int main(void) { struct date new_date; struct date old_date; s
amisauv
A C programme which can print the file name it is kept in on Tue 9th Dec 9am
#include<stdio.h> main(){ printf(”the source file name is %s\n”,__FILE__); } actually __FILE__ is a macro which stands for the file name the programme is kept in and the compiler does the rest .. for you ..
amisauv
BOOTSECTOR EDITOR: on Tue 9th Dec 9am
Code : /*program to save the partion table of your hard disk for future use. it will save your partition table in a file partition.dat */ #include<stdio.h> #include<bios.h> #include<conio.h> #include<stdlib.h> #include<ctype.h> void main () {
amisauv
BLINKING STAR : on Tue 9th Dec 9am
#include<conio.h> #include<graphics.h> #include<stdlib.h> #include<dos.h> void main() { int gdriver=DETECT,gmode; int i,x,y; initgraph(&gdriver,&gmode,"e: cgi"); while(!kbhit()) { x=random(640); y=random(480); setcolor
amisauv
// To print semicolons using C programming without using semicolons any where i on Tue 9th Dec 9am
// To print semicolons using C programming without using semicolons any where in the C code in program. // #include<stdio.h> #include<conio.h> void main() { char a; a=59; if(printf("%c",a)){} getch();

Test Yourself: (why not try testing your skill on this subject? Clicking the link will start the test.)
BSD sockets API by skrye

This is a test of your knowledge of the BSD socket interface
C Programming by keoki

This test is aimed at a C programmer that is at an intermediate level.


     
Your Ad Here
 
Copyright Open Source Institute, 2006