기본 데이터 삽입 절차
MySQL C API를 통해 데이터베이스에 일반적인 데이터를 삽입하는 과정은 다음과 같습니다:
- 데이터베이스 핸들 초기화: init 함수 호출
- 데이터베이스 연결: real_connect 함수 사용
- SQL 쿼리 실행: real_query 함수로 명령 전달
- 연결 종료: close 함수 호출
핵심 함수 설명
핸들 초기화
mysql_init(MYSQL *mysql)
데이터베이스 연결
MYSQL *
mysql_real_connect(MYSQL *mysql,
const char *host,
const char *user,
const char *passwd,
const char *db,
unsigned int port,
const char *unix_socket,
unsigned long client_flag)
연결 실패 시 NULL 반환, 성공 시 첫 번째 매개변수와 동일한 값 반환.
쿼리 실행
int
mysql_real_query(MYSQL *mysql,
const char *stmt_str,
unsigned long length)
연결 종료
void
mysql_close(MYSQL *mysql)
실제 구현 예시
#include <mysql.h>
#include <stdio.h>
#include <string.h>
#define SERVER_PORT 3306
#define SERVER_IP "192.168.189.128"
#define USERNAME "admin"
#define PASSWORD "197523@cyr"
#define DATABASE_NAME "YU_DB"
#define INSERT_QUERY "INSERT TBL_USER(U_NAME, U_GENGDER) VALUES('yu', 'woman');"
int main(){
MYSQL connection;
if(NULL == mysql_init(&connection)){
printf("초기화 오류: %s\n",mysql_error(&connection));
return -1;
}
if(!mysql_real_connect(&connection,SERVER_IP,USERNAME,PASSWORD,DATABASE_NAME,SERVER_PORT, NULL,0)){
printf("연결 오류: %s\n",mysql_error(&connection));
}
if(mysql_real_query(&connection,INSERT_QUERY,strlen(INSERT_QUERY))){
printf("쿼리 실행 오류: %s\n",mysql_error(&connection));
}
mysql_close(&connection);
return 0;
}
이미지 데이터 처리 방법
데이터 타입 선택
이미지와 같은 바이너리 대용량 객체는 BLOB(Binary Large Object) 타입으로 저장합니다. MySQL에서 제공하는 BLOB 타입은 다음과 같습니다:
- TINYBLOB
- BLOB
- MEDIUMBLOB
- LONGBLOB
테이블 구조 변경 예시:
ALTER TABLE TBL_USER ADD U_IMAGE LONGBLOB;
ALTER TABLE TBL_USER MODIFY U_IMG LONGBLOB;
PreparedStatement 활용
바이너리 데이터 처리를 위해 PreparedStatement 방식을 사용합니다. 이 방식의 장점은 다음과 같습니다:
- 쿼리 파싱을 한 번만 수행하여 성능 향상
- 네트워크 트래픽 감소
- 바이너리 프로토콜 사용으로 효율적인 데이터 전송
이미지 삽입 절차
- Statement 핸들 초기화: init과 prepare
- 파라미터 바인딩: bind_param
- 데이터 전송: send_long_data
- 쿼리 실행: execute
- 핸들 종료: close
구현 코드
쿼리 준비
INSERT TBL_USER(U_NAME, U_GENDER, U_IMG) VALUES('King', 'man', ?)
핸들 초기화
MYSQL_STMT *
mysql_stmt_init(MYSQL *mysql)
int
mysql_stmt_prepare(MYSQL_STMT *stmt,
const char *stmt_str,
unsigned long length)
파라미터 설정
MYSQL_BIND param = {0};
param.buffer_type = MYSQL_TYPE_LONG_BLOB;
param.buffer = NULL;
param.is_null = 0;
param.length = NULL;
파라미터 바인딩
bool
mysql_stmt_bind_param(MYSQL_STMT *stmt,
MYSQL_BIND *bind)
데이터 전송
bool
mysql_stmt_send_long_data(MYSQL_STMT *stmt,
unsigned int parameter_number,
const char *data,
unsigned long length)
실행 및 종료
int mysql_stmt_execute(MYSQL_STMT *stmt)
bool mysql_stmt_close(MYSQL_STMT *stmt)
이미지 조회 절차
- Statement 핸들 초기화
- 결과셋 바인딩
- 쿼리 실행
- 결과 캐싱 및 데이터 추출
- 핸들 종료
조회 구현 예시
int mysql_read_image(MYSQL* conn, char* buffer, int length){
if(conn == NULL || buffer == NULL || length <= 0) return -1;
MYSQL_STMT* stmt = mysql_stmt_init(conn);
int ret = mysql_stmt_prepare(stmt, SELECT_QUERY, strlen(SELECT_QUERY));
if(ret){
printf("준비 오류: %s\n", mysql_error(conn));
return -2;
}
MYSQL_BIND result = {0};
result.buffer_type = MYSQL_TYPE_LONG_BLOB;
unsigned long total_length = 0;
result.length = &total_length;
ret = mysql_stmt_bind_result(stmt, &result);
if(ret){
printf("결과 바인딩 오류: %s\n",mysql_error(conn));
return -3;
}
ret = mysql_stmt_execute(stmt);
if(ret){
printf("실행 오류: %s\n",mysql_error(conn));
return -4;
}
ret = mysql_stmt_store_result(stmt);
if(ret){
printf("결과 저장 오류: %s\n",mysql_error(conn));
return -5;
}
while(1){
ret = mysql_stmt_fetch(stmt);
if(ret != 0 && ret != MYSQL_DATA_TRUNCATED)break;
int offset = 0;
while(offset < (int)total_length){
result.buffer = buffer + offset;
result.buffer_length = 1;
mysql_stmt_fetch_column(stmt,&result, 0, offset);
offset += result.buffer_length;
}
}
ret = mysql_stmt_close(stmt);
if(ret){
printf("종료 오류: %s\n", mysql_error(conn));
return -6;
}
return total_length;
}
주요 함수 상세 설명
mysql_stmt_execute()
PreparedStatement와 관련된 쿼리를 실행합니다. 바인딩된 파라미터 값을 서버로 전송하고, 새로운 데이터로 치환합니다.
반환값: 성공 시 0, 오류 발생 시 비0값
mysql_stmt_send_long_data()
대용량 파라미터 데이터를 분할하여 서버로 전송합니다. mysql_stmt_bind_param() 이후, mysql_stmt_execute() 이전에 호출해야 합니다.
bool
mysql_stmt_send_long_data(MYSQL_STMT *stmt,
unsigned int parameter_number,
const char *data,
unsigned long length)
절차별 비교 요약
| 직접 실행 | PreparedStatement 삽입 | PreparedStatement 조회 |
|---|---|---|
| init → real_connect → real_query → close | init/prepare → bind_param → send_long_data → execute → close | init/prepare → bind_result → execute → store_result/fetch/fetch_column → close |