C ile MySQL Programlama

Bu yazıda C programlama dilini kullanarak MySQL veritabanına bağlanan programlar yapmayı öğreneceğiz. Döküman tahribat.com için j4x tarafından yazılmıştır. Örnekler gcc, MinGW ve Visual C++ derleyicisi -son sürümleri- kullanılarak test edilmiş ve çalışmaktadır. Bu döküman bir MySQL dersi değildir, MySQL bilenleri hedef alır. Fakat yine de basit işlemleri öğrenmenizi sağlayabilir.

MySQL C Kütüphanesinin Yüklenmesi

Linux (Ubuntu) İçin: sudo apt-get install mysql-server mysql-client libmysqlclient16-dev

Windows İçin: Eğer derlemeyi Visual C++ kullanarak yapmak istiyorsanız, MySQL_Dizini\lib\libmysql.lib dosyasını alıp Visual C++ içindeki lib klasörüne atın. Aynı şekilde include klasörünün içindekileri de Visual C++ içindeki include klasörüne atın. Eğer derlemeyi MinGW ile yapacaksanız iş biraz daha zahmetli. libmysql.a dosyası MySQL de kendiliğinden mevcut olmadığı için .lib dosyasını .a formatına çevirmeniz gerekiyor, bu da bilgisayardan bilgisayara ve versiyondan versiyona sorun çıkarıyor. O yüzden daha kolay ve sorunsuz bi yöntem olarak Xampp yüklemeyi öneriyorum. Xampp'ı kurduktan sonra xampp_dizini/mysql/ içindeki lib ve include klasörlerini mingw (ya da dev c++) dizini içine kopyalıyoruz. Daha sonra derleyicimizin lib klasörü içindeki libmysql.lib dosyasının adını değiştirip libmysql.a yapıyoruz. Eğer libmysql.dll hatası alırsanız mysql dizininizin lib klasörü içerisindeki libmysql.dll dosyasını projemizin .exe dosyasıyla aynı klasöre atıyoruz.

Windows ve MinGW Kullanıcılarına Not: Ben .lib dosyasını .a dosyasına çevirmek istiyorum isim değiştirmekle olmadı diyen varsa, Bu linkten pexports programını indirsin. Daha sonra komut satırından (cmd) mysql klasörü içindeki lib klasörüne girip "pexports libmysql.dll > libmysql.def" yazsın ve çıkan .def dosyasını aynı klasördeki libmysql.dll ile beraber derleyicisinin bin klasörüne kopyalasın. Daha sonra komut satırından derleyicisinin bin klasörüne gelip "dlltool -k --input-def libmysql.def --dllname libmysql.dll --output-lib libmysql.a" yazsın ve bu .def dosyasını kullanarak libmysql.a dosyasını oluşturmayı denesin. Sorun çıkma ihtimali yüksek o yüzden yukarıdaki yöntemi buna tercih ediyorum.

MySQL C kütüphanesinin kurulumu bu kadar. Bunu yapabildiyseniz muhtemen dökümanın kalan kısmında sorun olmayacaktır :))

Projeye .lib Dosyalarının Eklenmesi

MySQL C kütüphanesini kullanacak bir proje yapmak istediğiniz bu kütüphane dosyasını projenize eklemeniz gerekmektedir. Bunun için:

* Eğer Linux'ta gcc kullanıyorsanız, derleme satırına "$(mysql_config --libs) $(mysql_config --cflags)" ekleyin.

* Eğer komut satırından MinGW kullanıyorsanız derleme satırına "-lmysql" direktifini ekleyiniz.

* Eğer DevCpp kullanıyorsanız (ki o da varsayılan derleyici olarak MinGW kullanır) menüden Tools > Compiler Options kısmına girerek aşağıdaki resimde gözüktüğü gibi linker direktiflerine "-lmysql" ekleyiniz.

Dev C++ Linker Direktiflerinin Eklenmesi

* Eğer Visual C++ kullanıyorsanız Solution Explorer penceresinde projenize sağ tıklayarak Properties seçin. Property Pages penceresi açıldığında, aşağıdaki resimdeki gibi libraryler arasına libmysql.lib ekliyoruz.

Visual C++ Linker Direktiflerinin Eklenmesi

Bunları yaptıktan sonra Projenizde #include <mysql.h> yazarak mysql başlık dosyasını eklemeyi unutmayın.

Artık Koda Geçelim...

Yukarıdaki zımbırtıları hallettiğinizi varsayarak koda geçiyoruz. Bildiğiniz gibi veritabanı üzerinde işlem yapabilmek için ilk olarak bir bağlantı sağlamamız lazım. Bunu MySQL C API kullanarak yapmak için ilk olarak bir MYSQL işaretçisine ihtiyacımız var. Aşağıdaki şekilde tanımlıyoruz.

#include <stdio.h>
#include <stdlib.h>
//#include <windows.h> // Program Windows'ta çalışacaksa satırın başındaki yorum işaretlerini kaldırın
#include <mysql.h>

int main(void)
{
	MYSQL *conn = NULL;
	
	conn = mysql_init(NULL);

	if (conn == NULL)
	{
		printf("Hafiza yetersiz. Nesne hazirlanamadi.\n");
		exit(EXIT_FAILURE);
	}
	
	mysql_close(conn);
	
	getchar();
	return 0;
}

Tanımladığımız conn değişkeni, bağlantıyı temsil edecek işaretçidir. Henüz bir bağlantı sağlamış değiliz yalnızca nesneyi hazırladık. Bağlantıyı sağlamak için mysql_real_connect() fonksiyonunu kullanıyoruz.

#include <stdio.h>
#include <stdlib.h>
//#include <windows.h> // Program Windows'ta çalışacaksa satırın başındaki yorum işaretlerini kaldırın
#include <mysql.h>

int main(void)
{
	MYSQL *conn = NULL;
	
	conn = mysql_init(NULL);

	if (conn == NULL)
	{
		printf("Hafiza yetersiz. Nesne hazirlanamadi.\n");
		exit(EXIT_FAILURE);
	}
	
	if (NULL == (mysql_real_connect(conn, "localhost", "root", "123456", "veritabani1", 0, NULL, 0)))
	{
		printf("Baglanti saglanamadi, Hata: %s\n", mysql_error(conn));
		exit(EXIT_FAILURE);
	}
	
	mysql_close(conn);
	
	getchar();
	return 0;
}

Bu kodda veritabanının "localhost" ta çalıştığı (ne olduğunu bilmiyorsanız muhtemelen localhostta çalışıyordur ellemeyin.), bağlantıda kullanılacak kullanıcı adının "root" olduğu, root'un şifresinin "123456" olduğu ve üzerinde işlem yapılacak veritabanının "veritabanı1" adında olduğunu söyledik. Siz buraları kendi bilgilerinizle değiştirin. mysql_real_connect()'in bağlantı sağladığını öğrendik, şimdi ise işlemlere geçelim. Burada SELECT, INSERT, UPDATE ve DELETE deyimlerini göreceğiz. Aslında son üçünün kullanımı aynı olduğundan onlardan bir tanesini göreceğiz sorguyu değiştirerek diğerlerini kullanabilirsiniz.

Veritabanında Ekleme, Silme ve Güncelleme İşlemleri

Bunun için bir fonksiyon daha öğreneceğiz. Bu fonksiyonumuz mysql_query(). Veritabanımızda id (int), ad (varchar 30) ve soyad (varchar 30) alanlarını içeren "ogrenciler" adında bir tablomuz olduğunu farzedelim. Bu tabloya kullanıcıdan aldığımız bilgilere göre kayıt eklemek istiyoruz. Aşağıdaki gibi bir kod işimizi görür.

#include <stdio.h>
#include <stdlib.h>
//#include <windows.h> // Program Windows'ta çalışacaksa satırın başındaki yorum işaretlerini kaldırın
#include <mysql.h>

int main(void)
{
	MYSQL *conn = NULL;
	char sorgu[255] = {0};
	int id = 0;
	char ad[31] = {0};
	char soyad[31] = {0};
	
	conn = mysql_init(NULL);

	if (conn == NULL)
	{
		printf("Hafiza yetersiz. Nesne hazirlanamadi.\n");
		exit(EXIT_FAILURE);
	}
	
	if (NULL == (mysql_real_connect(conn, "localhost", "root", "123456", "veritabani1", 0, NULL, 0)))
	{
		printf("Baglanti saglanamadi, Hata: %s\n", mysql_error(conn));
		exit(EXIT_FAILURE);
	}
	
	printf("ID giriniz: ");
	scanf("%d", &id);
	getchar();
	
	printf("Ad giriniz: ");
	scanf("%s", ad);
	getchar();
	
	printf("Soyad giriniz: ");
	scanf("%s", soyad);
	getchar();
	
	sprintf(sorgu, "INSERT INTO ogrenciler VALUES(%d, '%s', '%s')", id, ad, soyad);
	
	if (mysql_query(conn, sorgu))
	{
		printf("Sorgu calistirilamadi!, Hata: %s\n", mysql_error(conn));
		exit(EXIT_FAILURE);
	}
	
	printf("Ekleme basarili!\n");
	
	mysql_close(conn);
	
	getchar();
	return 0;
}

Burada yaptığımız kullanıcıdan bilgileri alıp, bir karakter dizisine yazdırmak ve daha sonra bunu SQL sorgu metni olarak kullanmak. Burada INSERT INTO deyimi yerine UPDATE ve DELETE deyimlerini de kullanabiliriz, kullanım da bir değişikliğe gerek yoktur. Örneğin yukarıdaki tablo için sorgu değişkeninde "UPDATE ogrenciler SET id = 5 WHERE ad = 'Ahmet'" gibi bi sorgu ile ad'ın Ahmet olduğu kaydın id değerini 5 yapabiliriz. Aynı şekilde 3 numaralı id değerine sahip kişiyi silmek için "DELETE FROM ogrenciler WHERE id = 3" sorgusu kullanılabilir. Kısacası değişmesi gereken kısım mysql_query() fonksiyonunun 2. parametresindeki stringden ibarettir.

Şimdi ise SELECT deyimi ile veritabanından veri çekmeyi gösterelim.

SELECT Deyimi ile Veritabanından Veri Çekmek

Yine yukarıda verdiğimiz öğrenci tablosunu kullanacağız. Tablonun içinin dolu olduğunu farzedelim. Tablodaki kayıtları ekrana yazdırmak için aklımıza gelebilecek en basit sorgulardan biri olan "SELECT * FROM ogrenciler" sorgusunu kullanalım.

#include <stdio.h>
#include <stdlib.h>
//#include <windows.h> // Program Windows'ta çalışacaksa satırın başındaki yorum işaretlerini kaldırın
#include <mysql.h>

int main(void)
{
	MYSQL *conn = NULL;
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;
	
	conn = mysql_init(NULL);

	if (conn == NULL)
	{
		printf("Hafiza yetersiz. Nesne hazirlanamadi.\n");
		exit(EXIT_FAILURE);
	}
	
	if (NULL == (mysql_real_connect(conn, "localhost", "root", "123456", "veritabani1", 0, NULL, 0)))
	{
		printf("Baglanti saglanamadi, Hata: %s\n", mysql_error(conn));
		exit(EXIT_FAILURE);
	}
	
	if (mysql_query(conn, "SELECT * FROM ogrenciler"))
	{
		printf("Sorgu calistirilamadi!, Hata: %s\n", mysql_error(conn));
		exit(EXIT_FAILURE);
	}
	
	result = mysql_store_result(conn);
	
	printf("ID\tAd\tSoyad\n");
	printf("=====\t=====\t=====\n");
	
	while ((row = mysql_fetch_row(result)))
	{
		printf("%s\t%s\t%s\n", row[0], row[1], row[2]);
	}
	
	mysql_free_result(result);
	
	mysql_close(conn);
	
	getchar();
	return 0;
}

Bu programda da 2 yeni fonksiyon öğreniyoruz. Bunlar mysql_store_result() ve mysql_fetch_row(). mysql_store_result() fonksiyonunu, SELECT sorgusunu çalıştırdıktan sonra veritabanındaki sonuçları almak için kullanıyoruz. mysql_fetch_row() ise sonuç setindeki tüm sonuçlar boyunca döngüyü döndürmek için kullanılır. row değişkenini veritabanındaki bir satır olarak düşünelim (ki zaten o anlamda kullanılmış). row[0] satırdaki ilk sütun, row[1] ikinci sütun, ... Bu şekilde devam etmektedir. Veritabanından tüm sonuçlar karakter dizisi olarak döneceği için hepsinde %s kullandık, '\t' karakteri de bildiğiniz gibi tab karakteri yerine geçiyor, yalnızca konsolda metin hizalama amaçlı kullandık.

Son olarak bir de mysql_real_escape_string() fonksiyonunu gösterelim.

MySQL Özel Karakterlerini Anlamsızlaştırmak

İngilizce escaping deyimine 'anlamsızlaştırmak' diye bir Türkçe karşılık uyduruverdim, mazur görün :P. mysql_real_escape_string() fonksiyonu MySQL özel karakterlerini anlamsızlaştırmak için kullanılır (Phpci arkadaşlar iyi bilir). Örneğin verdiğimiz INSERT örneğini düşünelim. Adamın ismi Kel'Thuzad (evet aklıma başka bişey gelmedi) yani isminde ' karakteri geçiyor. Sorgu şu şekilde olacaktır: "INSERT INTO ogrenciler VALUES(1, 'Kel'Thuzad', 'Yogurtcuoglu')". MySQL burdaki ' karakterinin stringin sonumu yoksa ismin bir parçası mı olduğunu anlayamaz. Daha doğrusu stringin sonu olarak algılar. Dolayısıyla sorgunuz syntax hatası verecektir. Bu gibi MySQL özel karakterlerinin kullanılacağı durumlarda (hatta her zaman) mysql_real_escape_string() fonksiyonu oldukça faydalıdır. Hele ki kullanıcıdan giriş alıyorsanız, güvenlik açısından kullanmalısınız.

Not: mysql_real_escape_string() fonksiyonu için aktif bir MySQL bağlantısı gerekir, sebebi karakter seti bilgisinin bağlantıdan alınmasıdır.

Kodu bir daha yazmak yerine INSERT örneğimize bazı eklemeler yapacağız.

İlk olarak başlık dosyalarımızın arasında string.h başlık dosyasını ekliyoruz.

#include <string.h>

Ardından main() fonksiyonun içinde değişken tanımladığımız bölümde iki değişken daha tanımlıyoruz:

char guvenli_ad[30 * 2 + 1];
char guvenli_soyad[30 * 2 + 1];

Daha sonra aşağıdaki satırı buluyoruz.

sprintf(sorgu, "INSERT INTO ogrenciler VALUES(%d, '%s', '%s')", id, ad, soyad);

ve bu şekilde değiştiriyoruz:

sprintf(sorgu, "INSERT INTO ogrenciler VALUES(%d, '%s', '%s')", id, guvenli_ad, guvenli_soyad);

ve bu satırın üstüne aşağıdakileri ekliyoruz.

mysql_real_escape_string(conn, guvenli_ad, ad, strlen(ad));
mysql_real_escape_string(conn, guvenli_soyad, soyad, strlen(soyad));

Türkçe Karakter Sıkıntısı Yaşayanlara Öneriler

Eğer C ve MySQL programlarınızda Türkçe karakter sıkıntısı yaşıyorsanız işte size birkaç öneri.

* Türkçe karakter kullandığınız C programlarınızda setlocale fonksiyonu ile yereli Türkçeye çevirin.

#include <locale.h>
int main(void)
{
	setlocale(LC_ALL, "Turkish");
	return 0;
}

* MySQL bağlantısını sağlar sağlamaz bağlantının kullanacağı karakter setini belirleyin. Bunun için aşağıdaki gibi bir satır kullanabilirsiniz (eğer latin5_turkish_ci karşılaştırmasını kullanmak istiyorsanız).

mysql_query(conn, "SET NAMES 'latin5' COLLATE 'latin5_turkish_ci'");

Sonuç

Bu yazımızda C programlama dili kullanarak MySQL veritabanını kullanan programlar yapmayı öğrendik. En azından bir giriş yaptık :). Eğer MySQL C API hakkında daha fazla bilgi edinmek isteyen varsa bu linkten faydalanabilir. Okuyan herkese yararlı olmasını dileyerek dökümanı burada sonlandırıyorum. Çalıntı yapmazsanız mesud oluruz.

Tarih:
Hit: 329063
Yazar: j4x



Yorumlar


Siftahı yapan siz olun
Yorum yapabilmek için üye girişi yapmalısınız.