mysql 이 웹에서 가장 많이 사용되는 RDBMS 라는 데는 의심의 여지가 없는 것 같다. 주로 Apache 와 PHP 와 연동해서 사용되어 지는데 (이 3가지 조합을 APM 이라고 한다), 간단한 카운터, 방명록에서 부터, 좀더 복잡한 쇼핑몰, 스케쥴관리, 게시판, 웹메일 등 거의 쓰이지 않는 곳이 없을 정도이다.
Mysql 이 PHP 와 함께 웹에서 사용하는게 가장 일반적인 용도이긴 하지만, 많은 경우 시스템레벨에서 직접 다루어야 하는경우도 생긴다. 이러한 경우를 위해서 mysql 은 Perl, Python, C, C++ 등 다양한 API를 제공하는데, 우선 C를 이용한 접근에 대해서 알아보도록 하겠다. (나중에 시간이 허락하면 C++ 을 이용한 mysql 접근에 대해서도 알아보도록 하겠습니다) 설명에 들어감에 앞서 이문는 여러분이 SQL과 RDBMS에 대한 개념과, mysql 의 설치 및 운영에 관련된 기본 사항은 알고 있다는 가정하에 쓰여졌으며, 설명을 위해 쓰인 코드들은 기능과 효율성에 염두를 둔 코드가 아닌 순수 스터디용 (돌아만가는)코드 임을 공지합니다. mysql과 SQL 에 대한 상세한 내용은 관련 서적이나 database.sarang.net을 참고하세요.
코드를 테스트 하기 전에 우선 여러분의 시스템에 mysql client 가 설치되어 있는지 확인을 해보바란다. 필자의 경우 mysql-3.23.46 이 설치되어 있으며, 인클루드 파일은 /usr/local/include/mysql 에 라이브러리 파일은 /usr/local/lib/mysql 설치되어 있다. 요즘 왠만한 Linux 배포판은 기본으로 mysql 이 설치되어 있으니, 위의 인클루드와, 라이브러리 경로가 어디에 있는지 확인만 하면 될것이다.
그럼 테스트를 위한 테이블을 만들고 테이블에 간단한 내용을 입력해보자, 테이블이 위치할 DB 는 test 이고 테이블의 이름은 address 이다. CREATE TABLE address ( name varchar(25) default NULL, address text, tel varchar(25) default NULL); | 이 테이블은 간단한 주소록인데, "이름", "주소", "전화번호" 를 저장하기 위해서 사용된다.
이제 테스트를 위해서 2개 정도의 data 를 입력하도록 하자. INSERT INTO address VALUES ('홍길동','경기도 연천 연천아파트','02-500-5000');INSERT INTO address VALUES ('아무개','광주광역시 서구 현대 아파트','015-000-1111'); | 우리가 만들 프로그램을 테스트 하기 위한 환경이 갖추어 졌다면, 이제 본격적으로 코드를 작성해 보도록 하겠다.
예제 : mysql_test.c #include <mysql.h>#include <string.h>#include <stdio.h>#define DB_HOST "127.0.0.1"#define DB_USER "root"#define DB_PASS "gkwlak"#define DB_NAME "test"#define CHOP(x) x[strlen(x) - 1] = ' ' int main(void){ MYSQL *connection=NULL, conn; MYSQL_RES *sql_result; MYSQL_ROW sql_row; int query_stat; char name[12]; char address[80]; char tel[12]; char query[255]; mysql_init(&conn); connection = mysql_real_connect(&conn, DB_HOST, DB_USER, DB_PASS, DB_NAME, 3306, (char *)NULL, 0); if (connection == NULL) { fprintf(stderr, "Mysql connection error : %s", mysql_error(&conn)); return 1; } query_stat = mysql_query(connection, "select * from address"); if (query_stat != 0) { fprintf(stderr, "Mysql query error : %s", mysql_error(&conn)); return 1; } sql_result = mysql_store_result(connection); printf("%+11s %-30s %-10s", "이름", "주소", "전화번호"); while ( (sql_row = mysql_fetch_row(sql_result)) != NULL ) { printf("%+11s %-30s %-10s", sql_row[0], sql_row[1], sql_row[2]); } mysql_free_result(sql_result); printf("이름 :"); fgets(name, 12, stdin); CHOP(name); printf("주소 :"); fgets(address, 80, stdin); CHOP(address); printf("전화 :"); fgets(tel, 12, stdin); CHOP(tel); sprintf(query, "insert into address values " "('%s', '%s', '%s')", name, address, tel); query_stat = mysql_query(connection, query); if (query_stat != 0) { fprintf(stderr, "Mysql query error : %s", mysql_error(&conn)); return 1; } mysql_close(connection);} | mysql 은 mysql 연결, query 결과 받아오기, 결과물의 Row 값을 저장등을 위한 몇개의 구조체가 존재한다.
MYSQL | 데이타 베이스에 연결했을때, 이 연결을 다루기 위해 사용되는 구조체 이다 | MYSQL_RES | (SELECT, SHOW, DESCRIBE, EXPLAIN)등의 쿼리를 내렸을때 그 결과를 다루기 위해 사용되는 구조체이다. | MYSQL_ROW | 이것은 데이타의 하나의 row 값을 가리킨다. 만약 row 값이 없다면 null 을 가르키게 된다. | MYSQL_FIELD | 이 구조체는 각 필드의 정보를 가지고 있다. 여기에는 필드의 이름, 타입, 크기 등의 정보를 가지게 된다. mysql 에서 DESC 쿼리를 내렸을때의 정보를 가지고 있다고 보면된다. | MYSQL_FIELD_OFFSET | mysql 필드 리스트의 위치를 가진다. |
이 프로그램이 하는 일은 최초 mysql DB에 연결을 한다음에 query 를 통하여 address 의 내용을 가져와서 화면에 출력시켜주고. 다음에 사용자 입력을 받아서 DB에 저장하는데까지다. 앞에서 말했듯이, 유저 인터페이스라든가 하는 기능적인 측면은 전혀 신경쓰지 않았다. 이러한 측면에 대해서는 나중에 curse 계열을 다루면서 연구하게 될것이다. 그럼 이제부터 소스를 분석해 보기로 하겠다.
mysql_init() 는 mysql DB에 연결하기 전에 가장 먼저 실행되며, mysql 연결 지시자를 초기화 하는 일을 한다. mysql_init()를 이용해서 mysql 연결을 초기화 하고 나서 mysql_real_connect 를 이용해서 mysql 서버에 실제로 접근하게 된다. 아규먼트로는 우리가 터미널에서 mysql 을이용해서 접근하는데 필요한, 호스트이름(DB_HOST), 유저계정(DB_USER), 계정에 대한 패스워드(DB_PASS), 접근 하고자 하는 DB이름(DB_NAME), 포트번호(DB_PORT) 등이 들어간다. 연결에 성공하면 connection 핸들 값을 넘겨주고 실패하게 되면 NULL 값을 넘겨 주게 된다. 어떤 이유로 실패했는지 자세한 내용을 알아보고 싶다면 mysql_error() 을 사용하라.
mysql 서버로의 연결까지 성공적으로 마쳤다면, 이제 query 를 이용해서 본격적인 작업에 돌입한다. mysql_query 를 통해서 필요한 query를 실행 시키면된다.
우리가 보통 사용하는 쿼리는 "SELECT, SHOW, DESC, EXPLAIN" 과 같이 쿼리에 그 결과 값(row)을 요청하는 것과, "INSERT, UPDATE, DELETE" 와 같이 그 결과 값이 필요 없는 명령어로 나누어 볼수 있다. row 값을 요청하지 않는 쿼리라면 필요가 없겠지만 row 값을 요청하는 쿼리라면 쿼리의 결과값을 저장해야 할것이다. 이럴때 mysql_store_result()를 이용해서 쿼리의 결과값을 되돌려 받을수 있다. mysql_store_result()를 통해서 쿼리의 결과값을 되돌려 받았다면, mysql_fetch_row()를 이용해서 row 단위로 결과 값을 가져올수 있다. 이 함수는 쿼리의 결과값에서 다음의 row 값을 가져오며, 더이상 가져올 row 값이 없다면 NULL 을 돌려준다.
가져온 row 에서의 각필드 값은 row[0] 에서 row[mysql_num_fields(result)-1] 에 저장되어 있으 므로, 해당 row 의 field 값을 쉽게 가져올수 있다.
mysql_store_result() 을 통해서 가져온 쿼리결과값을 더이상 사용할 필요가 없다면, 메모리를 되돌려줘야 하는데, mysql_free_result 를 통해서 되돌려주면 된다. mysql_store_result()를 사용했다면 반드시 mysql_free_result()를 사용해서 메모리를 해제 시켜줘야 한다. 그렇지 않으면 메모리 누수가 발생하게 된다.
mysql_free_result()까지 시켜주고 나서, fgets() 함수를 통하여서 "이름", "주소", "전화번호" 를 입력받아서, 입력받은 정보로 쿼리를 만들고 이를 mysql_query()를 이용해서 DB 에 적재하는 것을 마지막으로 예제의 설명이 끝났다.
누가 보더라도 이해하기 쉬운 코드일것이다. 이제 이 코드를 컴파일 해서 실행시켜 보는 일만 남았다.
gcc -o mysql_test mysql_test.c -I/usr/local/include/mysql -L/usr/local/lib/mysql -lmysqlclient | -I 과 -L 옵션을 이용해서 컴파일 시키는데 필요한 인클루드 파일과 라이브러리 파일이 있는 디렉토리를 명시해주면 된다. 위의 디렉토리는 필자가 가진 시스템의 경우이고, 위의 디렉토리는 시스템에 따라서 다를수 있으니 자신의 시스템 설정에 맞도록 옵션을 주고 컴파일 하기 바란다.
이상 간단하게 mysql API 를 살펴보았다. 위의 예제는 많은 mysql API 중의 극히 일부분만을 써서 꼭필요한 기능만 구현한것이다. 더 자세한 정보는 www.mysql.org 사이트를 참고하기 바란다 |
0