MY-SQL

MySQL Chapter Four (C API)

Documentation Version: 0.95

MySQL Version: 3.20.29

Overview

이 장은 MySQL 데이터베이스 시스템에서 지원하는 C 어플리케이션 프로그래밍 인터페이스 (API, Application Programming Interface)에 대해서 설명하고 있다. API는 local/remote에 관계없이 client 프로그램으로부터 MySQL 데이터베이스 엔진을 제어할 수 있는 함수들을 지원한다.

Preparation

MySQL을 사용하기 위해서는 C 프로그램의 상단에 mysql.h 라는 헤더 파일을 include 시킨다:

#include "mysql.h"

또한 math (암호화를 위해서 필요), mysqlclient 라이브러리를 링크시킨다:

cc -I/usr/include/mysql -L/usr/lib/mysql myapp.c -o myapp -lm -lmysqlclient

MySQL 인스톨이 일반적인 방법으로 이루어졌다면, 이 include 파일은 /usr/include/mysql에 위치해있으며, client 라이브러리들은 /usr/lib/mysql에서 찾을 수 있다.

만약 새로 만든 client 프로그램에 memory leak(메모리 누수 현상)이 있다면, --with-debug=yes 옵션으로 컴파일 할 수 있다. MySQL client 라이브러리에서 'safa_malloc' 패키지를 사용하기 위한 client 코드를 사용하기 위해서 이 옵션이 필요하다. 당신은 모든 메모리 leak의 리스트를 얻기 위해서 프로그램을 종료하기 전에 client 프로그램에서 TERMINATE(stdout)이나 my_end(1)을 호출할 것이다. 자세한 설명을 위해서는 소스 배포본의 mysys/safemalloc.c 파일을 체크하라.

아래는 SELECT를 실행해서, 결과 데이터를 화면으로 출력하는 간단한 MySQL client 프로그램이다. 모든 API 함수들이 포함되지는 않았지만, 일반적인 client 프로그램의 레이아웃에 대한 아이디어를 가져다 줄 것이다.

 

#include #include #include "mysql.h" MYSQL mysql; MYSQL_RES *res; MYSQL_ROW row; void exiterr(int exitcode) { fprintf( stderr, "%s\n", mysql_error(&mysql) ); exit( exitcode ); } int main() { uint i = 0; if (!(mysql_connect(&mysql,"host","username","password"))) exiterr(1); if (mysql_select_db(&mysql,"payroll")) exiterr(2); if (mysql_query(&mysql,"SELECT name,rate FROM emp_master")) exiterr(3); if (!(res = mysql_store_result(&mysql))) exiterr(4); while((row = mysql_fetch_row(res))) { for (i=0 ; i < mysql_num_fields(res); i++) printf("%s\n",row[i]); } if (!mysql_eof(res)) exiterr(5); mysql_free_result(res); mysql_close(&mysql); }


 

Client Functions

MySQL API는 MYSQL data structure (mysql.h에서 정의됨)를 사용하여 데이터베이스 엔진과 연결한다. 단일 client 프로그램에서 DB에 다중 연결을 할 수도 있다. 단, 각각의 연결은 각각 다른 MYSQL structure에 지정되어야한다.

쿼리가 성공적으로 수행된 후에, 만약 데이터가 client에게 리턴되면, 결과값은 mysql_store_result()나 mysql_use_result()를 통하여 전송될 것이다. 두 함수는 결과값을 MYSQL_RES structure에 저장한다. 두 함수의 차이점은 다음과 같다. mysql_store_result()는 결과값을 한꺼번에 client 메모리로 읽어들인다. 반면, mysql_use_result()는 결과값을 mysql_fetch_row()를 이용하여, 한 줄(row)씩 동적으로 client 메모리로 가져온다.

명심할 것은, mysql_use_result()는 써버의 리소스를 잡고 있다(tie up)는 것이다, 그리고 사용자의 행동이 예측불가능한 interactive application에는 쓸 수 없다.

오직 하나의 연결만이 mysql_user_result()를 사용할 수 있고, 이것은 가장 최근에 생성된 것이어야한다. 또한, 30초 동안(기본값) 아무런 동작이 없으면 mysqld 프로세스가 연결을 닫는다는 것을 주의하라.

mysql_fetch_row()에 의해서 결과치로부터 받은 데이터는 각 필드의 시작점을 가지고 있는 간단한 포인터 배열인 MYSQL_ROW structure에 들어간다.

 


 

mysql_affected_rows

SYNOPSIS:

int mysql_affected_rows(MYSQL *mysql)

DESCRIPTION:

가장 최근의 UPDATE, DELETE 또는 INSERT에 영향을 받은(affected) row의 수를 반환한다.

RETURN VALUE:

  • x > 0 : 바뀐/반환된 row의 수를 가리킨다.
  • 0 : 해당하는 데이터가 없다
  • -1 : 에러가 있는 쿼리. 예를 들어, INSERT 도중에 중복된 primary 키를 add하려고 한 경우.

EXAMPLE:

  • mysql_query( &mysql, "INSERT INTO gl_transact (acctnbr, amount) VALUES (12345, 651.30)" ); if ( mysql_affected_rows( &mysql ) < 0 ) fprintf( stderr, "Attempted to add duplicate primary key\n" );

    MySQL은 '테이블에 있는 모든 레코드 삭제' 같은 경우에 대해서 최적화되었다. 이 최적화는 MySQL이 이 경우에 영향을 받은 행(row)의 숫자인 0을 리턴할 것이다. Doing a 'select count(*) from the_table' before deleting all records will give you a value for the number of rows affected, though this value may change between the SELECT and and DELETE since MySQL 3.20.X does not support table locking. 이 버그는 3.21.x 버전에서 고쳐졌다. (역자주. 무슨 얘긴지 종 잡을 수가 없군.)

 


 

mysql_close

SYNOPSIS:

void mysql_close(MYSQL *mysql);

DESCRIPTION:

열려져있는 연결을 닫는다.

모든 작업이 완료된 후에는 mysql_close으로 connection을 닫아야한다. 만약 mysql_close를 호출하지않으면, mysql_connect에 의해서 생성된 thread는 내장 time-out에 도달할 때까지 살아있을 것이다. 그렇게 되면, 사용자가 많은 써버의 경우에는 비록 짧은 시간 동안이지만 아주 많은 메모리를 소모할 수도 있다.

만약 쿼리가 완료되기 전에 connection이 종료되면, client에게 결과값을 전달하기 위해서 시도를 하는 동안 쿼리는 계속 살아있을 것이다. 그리고 연결이 종료되었다는 통보를 받으면 종료된다.

디폴트 timeout은 동작 중인 쿼리에 대해서는 30초, 열린 connection에 대해서는 8시간이다.

RETURN VALUE:

None.

 


 

mysql_connect

SYNOPSIS:

MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd)

DESCRIPTION:

host에서 실행 중인 MySQL 데이터베이스에 연결한다. host의 값은 호스트 이름, 또는 IP address가 될 수 있다. user 파라미터는 사용자의 MySQL login ID이고, passwd 파라미터는 사용자의 암호이다.

주의: mysql_connect를 호출하기 전에 passwd를 암호화하지 말 것. 암호화는 client API에 의해서 자동적으로 이루어진다.

 

mysql_connect는 데이터베이스에 어떤 동작을 취하기 전에 호출해야한다.

You may optionally specify the first argument of mysql_connect to be (MYSQL*) 0 This will force the C API to automatically alloc memory for the connection structure and free it on close. The downside of this approach is that you can't retrieve an error message from mysql_connect when you use this option.

당신은 mysql_connect의 첫 번째 인자를 (MYSQL*) 0으로 지정할 수도 있다. (역자주. 무엇가 빠진 듯... 원문을 확인할 것) 이렇게 지정하면, C API는 자동으로 connection structure를 위한 메모리를 할당하고, 해제(free)시킨다. 단, 이 옵션을 쓰면 mysql_connect로부터 에러 메시지를 얻을 수 없다는 단점이 있다.

    • 만약 host가 NULL이면, 'localhost'로 처리된다.
    • 만약 user가 NULL이면, '현재 사용자'로 처리된다. Windows ODBC 상에서는, 현재 사용자를 생략할 수 없다. Unix 상에서는 현재 접속한 ID로 처리된다.
    • If password is NULL then only records in the user table without a password entry will be checked for a match. This allows the db-admin to setup the MySQL privilege system in such a way that a user gets different privileges depending on whether they have specified a password or not.
    • 만약 password가 NULL이면 ... 이것은 db-admin이 ... (해석 안 되네... 쩝...)

RETURN VALUE:

  • 만약 연결이 성공적으로 수행됐다면, mysql을 리턴한다.
  • 만약 실패라면 NULL을 리턴한다.

EXAMPLE:

  • MYSQL *mysql; if ( ( mysql = malloc( sizeof( MYSQL ) ) ) != NULL ) { if ( ! ( mysql_connect( mysql, "pr_server", "jqpublic", "mypasswd" ) ) ) { free( mysql ); exit( 1 ); } } free( mysql );

 


 

mysql_create_db

SYNOPSIS:

int mysql_create_db(MYSQL *mysql, const char *db);

DESCRIPTION:

mysql에 의해서 지정된 기계에 db라는 이름의 데이터베이스를 생성한다. 단 create 권한을 가진 user ID에 의해서 MYSQL 연결이 되어있어야한다. (사용자 권한에 대해서는 chapter 5를 참고하라)

RETURN VALUE:

  • 데이터베이스가 정상적으로 생성되면, 0을 리턴한다.
  • 만약 에러가 발생하면, 0이 아닌 값을 리턴한다. 에러 메시지는 mysql_error()로 확인할 수 있다.

 


 

mysql_data_seek

SYNOPSIS:

void mysql_data_seek(MYSQL_RES *res, uint offset);

DESCRIPTION:

쿼리 결과값에서 지정된 행(row)을 찾는다. mysql_use_result()에 의해서 생성된 연결에서는 쓸 수 없다.

RETURN VALUE:

None

 


 

mysql_drop_db

SYNOPSIS:

int mysql_drop_db(MYSQL *mysql, const char *db);

DESCRIPTION:

mysql에 의해서 지정된 machine으로부터 db라는 이름을 데이터베이스를 drop한다. 지정된 데이터베이스를 drop할 수 있는 권한을 가진 user id로 접속되어있어야한다. (사용자 권한에 대한 자세한 설명은 chapter 6을 참고하라)

RETURN VALUE:

  • 데이터베이스가 성공적으로 drop 됐다면, 0을 리턴한다.
  • 만약 에러가 발생하면, 0이 아닌 값을 리턴한다. 에러 메시지는 mysql_error를 호출하여 확인할 수 있다.

 


 

mysql_eof

SYNOPSIS:

int mysql_eof(MYSQL_RES *)

DESCRIPTION:

fetch할 자료가 더 있는지를 검사한다.

RETURN VALUE:

  • Non-zero : 만약, mysql_fetch_row()가 결과값을 모두 fetch했기 때문에, 더 이상 fetch할 것이 없다면, 0이 아닌 값(true)를 리턴한다.
  • 0 : mysql_fetch_row()가 fetch할 수 있는 데이터가 남아있음.

 


 

mysql_error

SYNOPSIS:

char *mysql_error(MYSQL *mysql)

DESCRIPTION:

mysql 연결에서 가장 최근에 호출된 MySQL 함수의 에러메시지를 리턴한다.

만약 에러가 발생하지 않았다면, empty string을 리턴한다.

 


 

mysql_fetch_field

SYNOPSIS:

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *handle);

DESCRIPTION:

테이블 필드의 타입이 무엇인지 알아낸다.

 


 

mysql_fetch_lengths

SYNOPSIS:

unsigned int *mysql_fetch_lengths(MYSQL_RES *mysql)

DESCRIPTION:

쿼리 결과값에 있는 모든 컬럼의 길이를 리턴한다. 만약 \0을 포함하고 있는 데이터를 받을 생각이라면, 당신은 이 함수를 필드 값의 실제 길이를 얻는데 써야한다.

 


 

mysql_fetch_row

SYNOPSIS:

MYSQL_ROW mysql_fetch_row(MYSQL_RES *mysql);

DESCRIPTION:

쿼리 결과로부터 다음 줄(row)을 불러온다. 더 이상 불러올 데이터가 없으면, NULL을 리턴한다.

 


 

mysql_field_seek

SYNOPSIS:

void mysql_field_seek(MYSQL_RES *result, int field)

DESCRIPTION:

컬럼 커서를 컬럼 번호 field로 옮긴다. 이때, field 값 x는 0 <= x <= mysql_num_fields(MYSQL_RES*)-1 이어야한다.

 


 

mysql_free_result

SYNOPSIS:

void mysql_free_result(MYSQL_RES *result);

DESCRIPTION:

쿼리 결과를 저장하고있는 메모리를 free시킨다. mysql_store_result()에 대한 결과값 사용을 마치고 호출해야한다.

 


 

mysql_get_client_info

SYNOPSIS:

char *mysql_get_client_info(void);

DESCRIPTION:

현재 쓰이고 있는 client 라이브러리의 버전 정보를 포함하고 있는 스트링을 리턴한다.

 


 

mysql_get_host_info

SYNOPSIS:

char *mysql_get_host_info(MYSQL *mysql);

DESCRIPTION:

host의 이름을 리턴한다 (mysql_connect와 host 인자(argument)는 같다).

 


 

mysql_get_proto_info

SYNOPSIS:

int mysql_get_proto_info(MYSQL *mysql);

DESCRIPTION:

연결에 쓰이고 있는 프로토콜의 버전을 얻는다. MySQL은 client 특성에 따라 동적인 프로토콜을 제공한다. 단, 3.20.x 버전에서는 아무런 일도 하지 않는다. but in future versions it will for example allow one client to connect using the current protocol, while another connects using encryption and compression.

 


 

mysql_get_server_info

SYNOPSIS:

char *mysql_get_server_info(MYSQL *mysql);

DESCRIPTION:

써버의 버전 번호를 리턴한다.

 


 

mysql_insert_id

SYNOPSIS:

int mysql_insert_id(MYSQL *mysql)

DESCRIPTION:

결과 변수인 'res'에서 AUTO_INCREMENT 필드를 위해서 생성된 ID를 리턴한다.

 


 

mysql_list_dbs

SYNOPSIS:

MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild);

DESCRIPTION:

mSQL 어플리케이션을 쉽게 포팅하기 위해서 제공되었다.

쿼리처럼 'SHOW databases [ LIKE wild-card ]'를 실행하는 것과 유사하다.

 


 

mysql_list_fields

SYNOPSIS:

MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char *wild);

DESCRIPTION:

mSQL 어플리케이션을 쉽게 포팅하기 위해서 제공되었다.

쿼리에서 'SHOW fields [FROM table] [FROM database] [LIKE wild-card]'를 하는 것과 유사하다.

 


 

mysql_list_processes

SYNOPSIS:

MYSQL_RES *mysql_list_processes(MYSQL *mysql);

DESCRIPTION:

MySQL 데이터베이스 엔진에서 현재 실행 중인 thread의 리스트를 얻는다. 단, process 권한을 가지고 있어야한다.

 


 

mysql_list_tables

SYNOPSIS:

MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild);

DESCRIPTION:

mSQL 응용 프로그램을 쉽게 포팅하기 위한 함수.

Similar to doing 'SHOW tables [FROM database]' as a query.

쿼리처럼 'SHOW tables [FROM database]'를 하는 것과 유사하다.

 


 

 

mysql_num_fields

SYNOPSIS:

int mysql_num_fields(MYSQL_RES *result);

DESCRIPTION:

이 매크로 함수는 쿼리 결과에 있는 컬럼(fields)의 숫자를 리턴한다.

EXAMPLE:

  • MYSQL mysql; MYSQL_RES *result; int fields; if ( mysql_query( &mysql, "SELECT * FROM emp_master" ) == 0 ) { result = mysql_store_result( &mysql ); if ( result != NULL ) { fields = mysql_num_fields( result ); printf( "Retrieved %u fields\n", fields ); } else printf( "Query failed\n" ); } else abort();

SEE ALSO:

mysql_list_dbsmysql_list_fieldsmysql_list_processesmysql_list_tablesmysql_store_resultmysql_use_result

 


 

mysql_num_rows

SYNOPSIS:

int mysql_num_rows(MYSQL_RES *result);

DESCRIPTION:

이 매크로 함수는 가장 최근에 mysql_list_dbsmysql_list_fieldsmysql_list_processesmysql_list_tables 또는 mysql_store_result에 의해서 리턴된 행수(number of row)를 리턴한다.

EXAMPLE:

  • MYSQL mysql; MYSQL_RES *result; int rows; if ( mysql_query( &mysql, "SELECT * FROM emp_master" ) == 0 ) { result = mysql_store_result( &mysql ); if ( result != NULL ) { rows = mysql_num_rows( result ); printf( "Retrieved %u rows\n", rows ); } else printf( "Query failed\n" ); } else abort();

SEE ALSO:

mysql_list_dbsmysql_list_fieldsmysql_list_processesmysql_list_tablesmysql_store_resultmysql_use_result

 


 

mysql_query

SYNOPSIS:

int mysql_query(MYSQL *mysql, const char *query);

DESCRIPTION:

mysql에 의해서 지정된 데이터베이스에 query에 의해서 지정된 SQL 쿼리를 실행한다. 쿼리가 성공적으로 실행되었다면, 0을 리턴한다. 에러 시에는 0이 아닌 값을 리턴한다. 에러 메시지를 확인하려면 mysql_error를 사용한다.

mysql_num_rows를 사용하면, 쿼리에 의해서 리턴된 행(row)의 수를 알 수 있다.

만약 INSERT하려는 테이블에 AUTO_INCREMENT 필드가 있다면, mysql_insert_id를 사용하여 새로 지정된 필드를 찾을 수 있다.

 


 

mysql_real_query

SYNOPSIS:

int mysql_real_query(MYSQL *mysql, const char *query, uint length);

DESCRIPTION:

This function is called by mysql_query after it does a strlen function call to calculate the length of the query string. 쿼리 스트링을 위해서 크기가 고정된 버퍼를 할당했다면, 이것을 쓸 수 있다.

만약 un-escaped \0 값을 가지고 있는 데이터를 가지고 있다면, 이 함수를 써야한다.

 


 

mysql_reload

SYNOPSIS:

int mysql_reload(MYSQL *mysql);

DESCRIPTION:

MySQL 데이터베이스 엔진이 사용자 권한 테이블을 다시 읽어들이고, 모든 캐쉬를 정리하고, 쓰이지 않는 모든 테이블을 close한다. 이 함수는 어떤 테이블에 isamchk를 실행하기 전에 꼭 호출해야한다.

단, 사용자가 reload 권한을 가지고 있어야한다.

 


 

mysql_select_db

SYNOPSIS:

int mysql_select_db(MYSQL *mysql, const char *db);

DESCRIPTION:

mysql에 의해서 지정된 기계(machine)의, db에 의해서 지정된 데이터베이스에 연결한다. 서버에 있는 MySQL 데이터베이스은 접속 확인을 위해서 mysql에 담겨있는 loing id와 암호를 사용한다.

mysql_select_db를 쓰려면, mysql_connect을 호출해야한다.

일반적으로 mysql_select_db는 데이터베이스에 쿼리를 시도하기 전에 호출되어야한다. 예외는 아래와 같은 쿼리이다.

SHOW DATABASES like 'A%';

SELECT 1+1; # SELECT without using tables.

 


 

mysql_shutdown

SYNOPSIS:

int mysql_shutdown(MYSQL *mysql);

DESCRIPTION:

MySQL 데이터베이스 엔진을 shutdown한다. 단, 사용자가 shutdown 권한을 가지고 있어야한다.

 


 

mysql_stat

SYNOPSIS:

char *mysql_stat(MYSQL *mysql);

DESCRIPTION:

커맨드 'mysqladmin version'과 유사한 정보를 문자 배열로 리턴한다. 이것은 실행시간(updatime), 실행 중인 thread, 질문들(역자주 쿼리가 아니라 질문?), reload되거나 open된 테이블에 대한 정보를 포함하고 있다. 이것은 본질적으로 mysqladmin 프로그램의 상태 옵션과 비슷하다.

 


 

mysql_store_result

SYNOPSIS:

MYSQL_RES *mysql_store_result(MYSQL *mysql);

DESCRIPTION:

결과를 읽는다. 써버로부터 결과를 가져오기 위해서는 mysql_store_result()나 mysql_use_result()를 써야한다. 쿼리가 성공적으로 실행되었다면, 두 함수 중의 어느 것이나 쓸 수 있다.

mysql_store_result()는 에러가 발생했거나, 리턴 데이터가 없는 경우에 NULL을 리턴한다. 에러 체크는 아래처럼 할 수 있다:

  • if (!(result=mysql_store_result(&mysql)) && mysql_num_fields(&mysql)) fputs(mysql_error(&mysql),stderr);

    메모리를 해제(free)시키려면 mysql_free_result()를 호출한다.

 


 

mysql_use_result

SYNOPSIS:

MYSQL_RES *mysql_use_result(MYSQL *mysql);

DESCRIPTION:

결과를 mysql_fetch_row()에 의해서 써버에서 동적으로 불러오는 것을 제외하면, mysql_store_result()와 같다. 이것은 써버에 ties up하기 때문에, interactive 응용 프로그램에서는 쓰여져서는 안 된다. 이 함수는 client의 메모리를 적게 사용한다.

 

about author

PHRASE

Level 60  머나먼나라

인간에게는 세가지 싸움이 있다. 첫째는 인간과 자연과의 싸움이요, 둘재는 인간과 사회와의 싸움이요, 셋째는 인간과 마음과의 싸움이다. -빅토르 마리 위고

댓글 ( 4)

댓글 남기기

작성