이전 | 다음



MySQL 강좌(Ⅲ)

허정수<나우누리:wertyu>


     

1. 들어 가는 말

    지난 호에서는 MySQL을 이용하여 간단하게나마 슈퍼 마켓에서 매출을 관리하는 예를 들어 SQL 언어에 대해서 간단히 살펴 보았다.
    기본적인 SQL 언어만 알아도 MySQL의 Client 프로그램을 이용하여 Data들을 관리할 수 있다. 하지만, SQL 언어를 모르거나 컴퓨터를 잘 다루지 못하는 사람들은 Database를 어떻게 쓸 수 있을까. 우리네 슈퍼마켓 아저씨들 중에서 SQL 언어를 사용해서 매출을 관리할 수 있을 아저씨들이 얼마나 있을까.

    이번 호에서는 MySQL의 C API에 대해서 알아본다. MySQL의 C API를 이용하면 C나 C++로 짠 프로그램에서 MySQL 서버에 접속을 할 수 있다. (우리네 슈퍼마켓 아저씨는 어려운 SQL 언어를 배울 필요가 없다. 슈퍼마켓 아저씨를 낮춰보는 것이 아니므로 항의하는 일이 없었으면 한다.)

    MySQL과 연동하는 방법은 C API만이 전부는 아니고, PHP3, Perl, MyODBC, JDBC를 이용하여 연동을 할 수 있다. 이번 회에서는 C API에 대해서 알아보도록 하고, 다음 회에서 PHP3와 MySQL을 이용하여 Web과 연동하는 법에 대해 알아 보도록 한다.

 

2. 프로그램 컴파일

    C API를 소개하기 전에 일단 gcc의 옵션을 잘 모르는 독자를 위해 MySQL의 C API를 이용한 소스 코드를 컴파일하는 방법에 대해서 알아 본다.
    먼저 다음의 예제를 보자.

      #include <stdio.h>
      #include <mysql.h>
      #include <errno.h>

      void main(void)
      { MYSQL mysql ;
              
      mysql_init(&mysql) ;

      if(!mysql_real_connect(&mysql, NULL, “사용자이름”,”암호”, NULL ,3306, (char *)NULL, 0))
      {printf(“%s\n”,mysql_error(&mysql));
      exit(1) ;}
      printf(“성공적으로 연결되었습니다.\n”) ;
      mysql_close(&mysql) ;}

    위의 예제는 MySQL 서버에 접속을 하여, 연결이 제대로 되었을 경우 ‘성공적으로 연결되었습니다.’라는 메시지를 출력하고 종료하는 프로그램이다. 연결이 안 될 경우 왜 연결이 안 되는지 출력을 하게 된다. 에러가 나면 글의 후반부에 있는 ‘문제 해결’ 부분을 읽어 보길 바란다. 일단 위에 나온 함수들의 설명은 뒤에 하고 컴파일을 하는 방법에 대해 알아 보자.
    위의 소스 코드가 con.c라고 가정을 한다면 다음과 같이 프롬프트에서 명령을 내리면 된다.

      $ gcc -o con con.c -I/usr/local/include/mysql
      -L/usr/local/lib/mysql -lmysqlclient

    이렇게 하면 con이라는 실행 파일이 생기게 된다. -I 옵션은 헤더 파일의 경로를 정한다.
    즉, mysql.h의 경로를 지정해 주며, 필자의 경우 그 경로가/usr/local/include/mysql이다. 각자 경로가 틀리므로 자신에게 맞게 변경을 하자. 보통 /usr/include/mysql 혹은/usr/local/include/mysql 혹은 /usr/include에 존재한다. /usr/include에 있을 경우에는 이 옵션을 주지 않아도 된다.
    -l 옵션은 링킹시 사용할 라이브러리를 지정한다.
    MySQL의 C API를 사용했을 경우에는 꼭 -lmysqlclient라는 옵션을 주어야 한다.

    -L/usr/local/lib/mysql 옵션은 mysqlclient라는 라이브러리의 경로를 지정한다. 이 옵션도 사용자에 따라 다르다. MySQL의 설치 시에 어디에 라이브러리를 설치했는지 확인하자. 지정된 디렉터리 밑에서 libmysqlclient.so 라는 라이브러리를 볼 수 있다.
    옵션과 경로를 잘 지정해 주었다면 위의 소스 코드는 잘 컴파일 되고, 실행시에 MySQL 데몬이 실행 중이라면 ‘성공적으로 연결되었습니다.’라는 메시지를 볼 수 있을 것이다.

 

3. C API 자료형

    C API에서 쓰이는 자료형에 대해서 알아 보자.
    MYSQL : Database와의 연결을 관리하는 구조체이다. 대부분의 C API 함수에서 쓰인다.
    MYSQL_RES : SELECT 등 결과를 리턴하는 query의 결과를 나타내는 자료형이다.
    MYSQL_ROW : MYSQL_RES에서 하나의 레코드씩 값을 얻어 올때 쓰이는 자료형이다.
    MYSQL_FIELD : 필드의 이름과 필드의 타입 등 필드에 관한 정보를 저장하는 자료형이다.

 

4. MySQL Database에 연결하기

    이제 모든 준비를 마췄으므로 본격적으로 MySQL C API에 대해서 알아보자.

    * MYSQL* mysql_init(MYSQL *mysql)
    mysql_real_connect()를 위하여 MYSQL 객체를 초기화한다. 특별히 하는 일은 없으나 MYSQL 객체를 초기화 하므로 mysql_real_connect() 전에 꼭 호출하여 주자.

    * MYSQL* mysql_real_connect(MYSQL* mysql, const char* host, const char* user,
    const char* passwd, const char* db, uint port, const char* unix_socket, uint client_flag)
    host에 지정된 서버로 연결을 시도하는 함수이다.
    mysql_get_client_info() 함수를 제외한 모든 API 함수를 사용하기 전에 꼭 호출하여야 하는 함수이다.
    각 인자에 대한 설명은 다음과 같다.

    mysql    : MYSQL 변수에 대한 포인터 형이다.
    host      : 연결하고자 하는 서버의 IP Address 혹은 도메인 이름을 적어주면 된다.
                  NULL로 적어주면 localhost를 의미한다.
    user      : 접속시의 사용자 이름이다. NULL이면 현재 login한 user ID가 된다.
    passwd : user의 암호를 나타낸다. NULL이면 암호가 없다는 의미이다.
    db        : 접속시에 사용하고자 하는 database를 나타낸다. NULL로 지정을 하면 연결 후에
                  mysql_select_db() 혹은 mysql_query()를 이용해서 지정할 수 있고,
                  database를 바꿀 수도 있다.
    port       : TCP/IP 연결시에 사용할 포트 번호를 나타낸다.
    unix_socket : 보통 NULL로 하면된다.
    client_flag   : 이 인자도 보통 0으로 해주면 된다.
    mysql_real_connect()는 성공적으로 연결이 되면, MYSQL 포인터를 넘겨주고 연결에 실패하였을 경우 NULL을 리턴한다.
    연결에 실패 하였을 경우 이 글이 마지막에 있는 ‘문제 해결’부분을 읽어 보길 바란다. 사용 예는 위의 예제에 나와있다.

    * void mysql_close(MYSQL* mysql)
    서버와의 연결을 끊고 mysql에 할당되었던 메모리를 해제한다.

 

5. Query와 결과 값을 얻어 오기

    서버와 성공적으로 연결이 되었다면, 이제 원하는 Query를 하고, 그 결과 값을 얻어 올 수 있다. Query를 할 수 있는 함수는 mysql_query()와 mysql_real query() 두 가지가 있다.

    * int mysql_query(MYSQL* mysql, const char* query) :
    query를 실행 시킨다. mysql 클라이언트에서 했던 것 처럼 query의 끝에 ‘;’가 포함되어서는 안 된다. query의 끝은 NULL 문자(‘\0’)이다. 따라서 바이너리 데이타가 섞인 query는 수행을 할 수 없다. 바이너리 데이타가 섞은 query의 중간에는 NULL 문자가 올 수도 있기 때문이다. query를 성공적으로 마췄다면 0을 리턴한다.

    * int mysql_real_query(MYSQL* mysql, const char* query, unsigned int length) :
    mysql_query()는 query의 끝을 NULL 문자로 구분을 하는데 반해, mysql_real_query는 query의 끝을 length 만큼의 길이로 구분한다. 따라서 NULL 문자를 포함한 바이너리 데이타가 있는 query도 수행을 할 수 있다. 또한mysql_query()는내부적으로strlen()를 사용하지만, mysql_real_query()는 그렇지 않으므로 좀더 빠르다. 마찬가지로 query를 성공적으로 수행하였을 경우 0을 리턴한다.
    위의 함수를 이용하여 query를 수행할 수가 있다. 호출하는 방법은 매우 간단하다.

    mysql_query(&mysql, “SELECT * FROM dome”) ;
    위와 같이 query를 수행하면 된다.
    query를 성공적으로 수행했다면, 이제 결과 값을 얻어 와야 한다.

    * MYSQL_RES* mysql_store_result(MYSQL* mysql)
    * MYSQL_RES* mysql_use_result(MYSQL* mysql)
    위 두 함수는 모두 서버로부터 결과 값을 얻어 오는데, 차이는 query의 결과로 리턴되는 ROW들을 한꺼번에 모두 서버로부터 얻어 올 것인지(mysql_store_result()), 혹은 한번에 한 개의 ROW를 얻어 올 것(mysql_use_result())의 차이이다.
    mysql_store_result()는 ROW들을 한 꺼번에 모두 얻어와 클라이언트의 메모리에 저장을 한다. 따라서 매번 ROW를 얻어 오기 위해 서버에 접근을 할 필요가 없으므로 속도가 빠르다. 대신 결과로 넘어온 ROW의 크기가 클 경우 많은 메모리가 필요하게 된다.
    또 mysql_store_result()의 장점은 mysql_data_seek()나 mysql_row_seek()를 이용하여 현재 ROW에서 앞이나 뒤의 ROW로 자유자재로 왔다 갔다 할 수 있다는 것이다. 또한, mysql_num_rows()를 이용하여, 몇 개의 ROW가 리턴됐는지도 알 수 있다.

    반면 mysql_use_result()는 한 번에 한 개의 ROW를 서버로부터 가져 온다. 따라서 메모리를 많이 사용하지 않는다. 하지만, mysql_store_result()와 같은 장점을 가지 지 않는다. 리턴되는 ROW가 특별히 크지 않은 경우라면, 보통 mysql_store_result()를 호출하는 것이 좋다.

    결과 값을 얻어 왔다면 mysql_fetch_row()를 이용하여 각각의 row에 있는 데이타 들에 접근을 할 수 있다.

    MYSQL_ROW mysql_fetch_row(MYSQL_ROW* result)
    result에 있는 ROW들에서 한 개의 ROW를 얻어 온다. 한 개의 ROW에서 각각의 field는 배열 형태로 들어 있다. 더 이상 가져올 ROW가 없으면 NULL을 리턴한다.
    현재의 result에 몇 개의 field가 있는지 mysql_num_fields()를 이용하여 알 수 있다.

    int mysql_num_fields(MYSQL_RES* result)

    이제 실제로 query를 수행하고, 결과를 출력하여 보자.

      1:      #include <stdio.h>
      2:      #include <mysql.h>
      3:      #include <errno.h>
      4:
      5:      void main(void)
      6:      {
      7:      MYSQL           mysql ;
      8:      MYSQL_RES*      res ;   
      9:      MYSQL_ROW       row ;
      10:     int             fields ;
      11:             
      12:     mysql_init(&mysql) ;
      13:     
      14:     if(!mysql_real_connect(&mysql, NULL, “사용자”,”암호”, “test”, 3306, (char *)NULL, 0))
      15:     {
      16:     printf(“%s\n”,mysql_error(&mysql));
      17:                       exit(1) ;
      18:             }
      19:     
      20:     if(mysql_query(&mysql, “USE super”) )
               // mysql_query()는 query 수행시에 에러가 나게 되면
               // 0이 아닌 값을 리턴한다.
      {
      printf(“%s\n”, mysql_error(&mysql) ;
                              exit(1) ;
                        }
      21:     if(mysql_query(&mysql, “SELECT * FROM dome”) )
      {
      printf(“%s\n”, mysql_error(&mysql) ;
                              exit(1) ;
                                          }
      22:     
      23:     res = mysql_store_result( &mysql ) ;
      24:     fields = mysql_num_fields(res) ;
      25:     
      26:     while( ( row = mysql_fetch_row( res ) ))
      27:             {
      28:     for( cnt = 0 ; cnt < fields ; ++cnt)
      29:     printf(“%12s “, row[cnt]) ;
      30:
      31:     printf(“\n”) ;
      32:             }
      33:
      34:       mysql_free_result( res ) ;
      35:     mysql_close(&mysql) ;
      36:     }

    12번 줄은 mysql_init()을 이용하여 MYSQL 객체를 초기화 하는 과정이다.
    14번 줄은 실제 MySQL 서버와 연결을 시도하는 부분이다. 연결에 실패하였을 경우 NULL을 리턴하므로 15-18번 줄에서, 에러 메시지를 출력하고 프로그램을 종료한다.
    20번 줄은 “use super”라는 query를 이용하여 ‘super’ database를 사용하도록 지정하는 부분이다. 사용하고자 하는 database는 mysql_real_connect()에서 지정을 할 수도 있고, 프로그램 실행 중에 바꾸고자 할 때는 “use DB이름”과 같은query를 이용할 수도 있고, 혹은 mysql_select_db()를 이용할 수도 있다.
    21번 줄은 “SELECT * FROM dome” query를 수행하는 부분이다. dome 테이블의 모든 컬럼을 리턴하도록 하였다.
    23번 줄은 mysql_store_result()를 이용하여 결과 값을 저장하는 부분이다.
    24번 줄은 mysql_num_fields()를 이용하여 현재 결과 값에 몇 개의 필드가 있는지 알아 내는 부분이다.
    mysql_fetch_row()는 배열 형태로 각 필드에 접근을 하므로 배열의 인덱스를 알아내야 정확히 데이타들을 얻어 올 수 있다.

    26-32번 줄은 실제로 각 ROW들로부터 데이타에 접근하는 부분이다.
    mysql_fetch_row()를 이용하여 각각의 ROW를 얻어 온다(더이상 가져올 ROW가 없으면 NULL을 리턴한다.) 그 후 for문을 이용하여 ROW의 각각 필드를 출력하였다.
    34-35번 줄은 res와 mysql에 할당된 메모리를 해제하는 부분이다. 하지만, query에 따라서는 ROW를 리턴하지 않는 query도 있다(UPDATE나 DELETE등) 만약 위의 예제에서 사용자가 UPDATE 등을 수행하였다면, 곧바로 Segmentation Fault가 나버린다.
    이때는 mysql_num_fields()를 이용하여, 필드의 개수를 조사함으로써 문제를 해결할 수 있다. query가 ROW를 리턴하였다면, 필드는 최소한 0보다 크기 때문이다. 다음의 예제를 보자(참고로 밑의 예제는 MySQL Manual 19장에서 발췌한 내용이다.)

      MYSQL_RES*      result ;
      unsigned        int num_fields ;
      unsigned        int num_rows ;

      if(     mysql_query(&mysql, query_string) )
      {
      // mysql_query는 성공적으로
      // 수행할 경우 0을 리턴하므로
      // 이 부분이 실행 된다면
      // 에러가 있다는 의미이다.
      // 적절한 에러 핸들링을 해주다.
      }
      else // 성공적으로 query가 수행되었다.
      {
      result = mysql_store_result( &mysql ) ;
      if( result ) // 리턴된 ROW가 있다 !
      {
      num_fields = mysql_num_fields( result ) ;
      // row의 값을 얻어오는 루틴을 집어 넣으면 된다.
      // 마지막에는 mysql_free_result()를 이용하여
      // 메모리를 해제시키자.
      }
      else // 리턴된 ROW가 없다. ROW를 리턴하지 않는 query를 수행하였는지 // 혹은 query의 수행 중에 에러나 났는지 알 수 없다.
      {
      if( mysql_num_fields( &mysql ) == 0)
      {
      // ROW를 리턴하지 않는 query를 수행하였다.
      num_rows = mysql_affected_rows( &mysql ) ;
      // mysql_affected_rows()는 DELETE 등의
      // query에서 몇 개의 ROW가 영향을 받았는지
      // 리턴하는 함수이다.

      }
      else // 무언가 잘못된 것이 있다.
      fprintf(“stderr,Error : %s\n”,mysql_error( &mysql) ) ;
      // mysql_error()는 가장 최근의 에러를 리턴하는 함수이다.
      }
      }
      위의 예제를 이용하여, 결과를 리턴하는 query 든지(SELECT), 아니면 결과를 리턴하지 않는 query 든지(UPDATE, DELECT 등) 어떠한 query라도 수행을 성공적으로 할 수 있다.

    이번에는 ROW의 필드에 대한 정보를 얻어 오는 방법에 대해서 알아 보자. MYSQL_FIELD라는 구조체가 쓰이는데 MYSQL_FIELD에는 다음과 같은 멤버들이 있다.

    char* name  : 필드의 이름을 나타낸다.
    char* table : 현재 필드의 테이블 이름을 나타낸다.
    char* def   : 필드의 기본값을 나타낸다.

    MYSQL_FIELD* mysql_fetch_field( MYSQL_RES* result )
    : 한번에 하나의 MYSQL_FIELD를 리턴한다.
    MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES* result )
    : 배열의 형태로 모든 MYSQL_FIELD를 리턴한다.

      예1)
      MYSQL_FIELD *field ;
      while( (field = mysql_fetch_field(result) )
      printf(“field name %s\n”, field -> name ) ;

      예2)
      unsigned int num_fields ;
      unsigned int i ;
      MYSQL_FIELD* fields ;
      num_fields = mysql_num_fields( result ) ;
      fields = mysql_fetch_fields( result ) ;
      for( i = 0 ; i < num_fields ; ++i)
      printf(“field name %s\n”, fields[i].name) ;

    위의 두 개의 예는 모두 동일안 결과를 출력한다.

 

6. 문제 해결

    이번에는 C API를 사용한 소스 코드를 컴파일할 때 혹은, 실행 도중 만나는 문제점을 해결할 수 있는 방법을 설명한다.

      1) “con.c:2: mysql.h: 그런 파일이나 디렉토리가 없음”
         이 경우는 mysql.h의 경로를 찾을 수 없어서 나는 에러이다. 다시 한번 mysql.h가
         어디에 있는지 확인을 하고, -I옵션으로 그 경로를 지정해 주자. -I옵션과 경로는
         붙여 써야 한다.

      2) “con.o(.text+0x11): undefined reference to `mysql_init’”  위와 같이
          ‘undefined reference......’ 라고 나오는 에러는 -lmysqlclient 옵션을 주지 않았기
          때문이다.

      3) “ld: cannot open -lmysqlclient: 그런 파일이나 디렉토리가 없음” 위의 에러는
          -L옵션 뒤에 붙은 라이브러리의 경로가 잘못 되었기 때문이다.
            libmysqlclient.so 파일의 경로를 찾아서 그 경로로 지정을 해 주자.
          -I 옵션과 마찬가지로 -L과 경로는 붙여 써야 한다. 위의 에러들은 컴파일시에
            옵션이 잘못되었을 경우 나오는 에러 메시지이다.
            계속해서 프로그램의 실행 중에 나오는 에러 메시지를 보자.

      4) “Can’t connect to local MySQL server (2)”
          위의 에러는 MySQL의 서버에 연결을 할 수 없다는 메시지로서, MySQL 서버의
          데몬이 실행 중이지 않을 때 나오는 메시지이다.
          safe_mysqld 명령 등을 이용하여 데몬을 실행시켜 주자.

      5) “Access denied for user: ‘rot@localhost’ (Using password: YES)”
          접근이 금지되었다는 메시지로서 사용자 아이디를 잘못 입력하였 거나, 혹은 암호를
          잘못 입력하였을 때 나오는 메시지이다.
          MySQL의 사용자는 모두 mysql database의 user 테이블에 있으므로, 참고를 하여
          적도록 하자.

      6) “error in loading shared libraries libmysqlclient.so.6:
          cannot open shared object file: No such file or directory”
          MySQL의 라이브러리를 열지 못한다는 메시지이다. 컴파일 할 때 MySQL의 동적
          라이브러리를 사용하느데, 동적 라이브러리이므로 실행시에도 라이브러리가
          필요하게 된다.
          libmysqlclient.so가 /usr/lib 혹은 /usr/lib/mysql 디렉터리에 존재하지 않을 경우에
          발생하는 문제이다. 가장 간단한 해결법으로는 모든 MySQL 라이브러리를 /usr/lib/
          나 /usr/local/lib 밑으로 복사하는 것인데 별로 추천하는 방법은 아니다.
          두 가지 방법이 있는데,
          먼저 시스템의 운영자라면, /etc/ld.so.conf 파일에libmysqlclient.so가있는 경로를     적어 준 후에 ldconfig 라는 명령을 프롬프트에서 실행하여 주면 된다. 이러한 권한이
          없는 일반 사용자라면, 자신의 쉘의 환경 변수를 이용하면 된다.
          각자의 쉘이 맞게, LD_LIBRARY_PATH를 libmysqlclient.so가 있는 디렉터리로
          지정을 해주자.
          C 쉘 사용자는  setenv LD_LIBRARY_PATH  경로명 본 쉘 사용자는
          export LD_LIBRARY_PATH  경로명 이렇게 해주면 된다.
          보통 위의 6개의 에러가 가장 많이 발생한다. 혹시, 해결하지 못할 에러가 있다면
          필자에게 메일을 보내면 친절히 답변해 주겠다.

 

7. Quick Reference

    위에서 설명한 API만을 가지고도 서버에 연결하여, Query를 수행하고 그 결과를 확인 할 수 있다. 이번에는 C API의 중요한 함수들을 모아서, 함수의 프로토타입과 함수의 기능들에 대해서 간단히 알아도록 하자. 개인적으로 그다지 중요하지 않다고 생각되는 함수들은 제외시켰으므로 모든 C API를 보고 싶은 독자들은 MySQL Reference Manual의 19장을 보기 바란다. 참고로 필자가 참조한 메뉴얼은 MySQL 3.22.21용 메뉴얼이었다.

      1) my_ulonglong mysql_affected_rows(MYSQL* mysql) INSERT, UPDATE, DELETE
          등의 query로 영향을 받은 ROW의 수를 리턴한다.

      2) void mysql_close(MYSQL* mysql) 서버와의 연결을 종료한다.

      3) void mysql_data_seek(MYSQL_RES* result, unsigned int offset) result에서 임의의
          ROW에 접근을 하도록 하는 함수이다.
          offset이 row의 번호를 나타낸다. 0이면 처음 ROW,  mysql_num_rows( result ) - 1
          은 마지막 row를 나타낸다.

      4) unsigned int mysql_errno(MYSQL* mysql) 가장 최근에 mysql에 일어난 에러의
          번호를 리턴한다.

      5) char* mysql_error(MYSQL* mysql) 가장 최근에 일어난 에러 메시지를 리턴한다.

      6) MYSQL_FIELD*mysql_fetch_field(MYSQL_RES* result)한번 호출할 때마다 하나의
          필드에 대한 정보를 리턴한다.

      7) MYSQL_FIELDS*mysql_fetch_fields(MYSQL_RES* result) 배열형대로 result의
          필드에 대한 정보를 한꺼번에 리턴한다.

      8) MYSQL_FIELD_OFFSETmysql_field_seek(MYSQL* mysql,     MYSQL_FIELD_OFFSET offset)임의의 필드에 접근을 하도록 한다.

      9) MYSQL_FIELD_OFFSETmysql_field_tell(MYSQL_RES* result)현재 필드의 offset을
          리턴한다.

      10) void mysql_free_result(MYSQL_RES* result) result에 할당된 메모리를 해제한다.

      11) MYSQL* mysql_init(MYSQL* mysql) mysql 객체를 초기화한다.
            인자가 NULL이면 새로운 MYSQL 객체를 생성하고, 초기화하여 리턴한다.

      12) MYSQL_RES* mysql_list_dbs(MYSQL* mysql, const char* wild)
            현재 서버에 있는 데이타베이스의 목록을 리턴한다. wild는 MySQL에서 사용할 수
            있는 정규식을 나타낸다.     
           result = mysql_list_dbs( &mysql,”%” )는 모든 데이터베이스를 리턴하는 예이다.      (%는 ‘모든’을 나타낸다)

      13) MYSQL_RES* mysql_list_tables(MYSQL* mysql, const char* wild)
            현재 데이타베이스에 있는 테이블들의 목록을 리턴한다.

      14) unsigned int mysql_num_fields(MYSQL_RES*result) 혹은
            unsigned int mysql_num_fields(MYSQL* mysql)필드의 수를 리턴한다.

      15) my_ulonglong mysql_num_rows(MYSQL_RES* result) result에 총 몇 개의 ROW가
            있는지 리턴한다. query 수행 후 mysql_store_result()를 호출하였을 경우에만 사용
            할 수 있고, mysql_use_result()는 사용할 수 없다.

      16) int mysql_ping(MYSQL* mysql) 서버에 연결 중인지를 리턴한다. 연결이 끊어 졌을
            경우, 다시 연결을 시도한다. 서버와 연결을 한 후, 오랫동안 가만히 있으면 서버가
            연결을 끊어버리는데, 이런 경우에 사용한다.

      17) int mysql_query(MYSQL* mysql, const char* query) query가 포인트 하는 쿼리를
            수행한다. query의 끝은 NULL 문자이다. 성공적으로 query를 수행하였으면 0을
            리턴한다.

      18) MYSQL* mysql_real_connect(MYSQL* mysql, const char* host,
            const char* user, const char* passwd, const char* db, uint port,
            const char* unix_socket, unit client_flag ) host와의 연결을 시도한다.
            인자별로 자세한 설명은 윗 부분에 되어 있다.

      19) int mysql_real_query(MYSQL* mysql, const char* query,
            unsigned int length)mysql_query()처럼 query를 수행하나, query의 끝이 legnth인
            것이 다르다.

      20) MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES* result)현재 ROW의 offset을
            리턴한다.

      21) int mysql_select_db(MYSQL* mysql, const char* db)사용하고자 하는 database
            를 변경한다.
            mysql_query()를 이용하여 “use db이름”의 query를  수행해도 같은 결과를
            얻는다.

      22) int mysql_shutdown(MYSQL* mysql) 서버를 종료시킨다.
           현재 사용자에게 shutdown 권한이 있어야 한다.

      23) MYSQL_RES* mysql_store_result(MYSQL* mysql) query의 수행결과를 서버로
           부터 한 번에 모두 받아 온다.

      24) MYSQL_RES* mysql_use_result(MYSQL* mysql) query의 수행결과를 서버로부터
            한 개의 ROW 씩 받아 온다.




▲ top