개요
C API를 이용한 MySQL에서 Prepared Statment( pstmt ) 를 사용하여 Stored Procedure(이하 SP)를 호출하려함.
insert나 update부분쪽은 잘 되는것을 확인 하지만 SELECT에서 왜인지 모르게
특히 fetch관련 함수를 사용하면 핸들이 정상종료가 안되고 뒤 쿼리들도 망가지는 현상을 해결하지 못하여
다른 방법인 stored procedure에서 OUT 인자를 사용하여 전달하려했으나 이것도 좀 난항을 겪음
결국 pstmt를 사용하지 않고 일반 쿼리를 날렸으나 이것도 단순하게는 안되고 특정 방법을 사용해야 되기에 저장용으로 기술
CREATE DEFINER=`root`@`localhost` PROCEDURE `dummytest`(
in param1 varchar(20),
in param2 varchar(20),
out param3 smallint
)
BEGIN
select count(*) into param3 from player_data where player_name = param1 and player_password = param2;
END
mysql의 sp는 이정도. 간단한 쿼리이다.
이것을 호출하려면 sql 쿼리로는 call dummytest('id','pw',@param); 이렇게 된다.
내가 간과했던건 c++에서의 코드 작성 방법이다.
string id{ "test1" }, pw{ "1234" };
short is_ok{};
sprintf_s(query, 1024, "call dummytest('%s','%s',%d)", id.c_str(), pw.c_str(),is_ok);
지금보니 상당히 엉뚱한 코드인데, pstmt를 사용하면서
쿼리에 변수 binding을 했었어서 헷갈렸었던 것 같다.
정상적인 코드는 이렇다.
string id{ "test1" }, pw{ "1234" };
sprintf_s(query, 1024, "call dummytest('%s','%s',@param3)", id.c_str(), pw.c_str());
sql에 쿼리 날리는것과 동일하게 날려야한다는 점. @도 빼먹으면 안된다.
그러면 param3는 어떻게 얻나?
sprintf_s(query, 1024, "select @param3");
단순하게 @param3을 얻는 쿼리를 한 번 더 치면 된다...... 이상 끝
코드 전문
MYSQL* hmysql;
MYSQL* conn_result;
unsigned int timeout_sec = 1;
hmysql = mysql_init(NULL);
mysql_options(hmysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout_sec);
conn_result = mysql_real_connect(hmysql, "localhost", "root", "dltnals", "simplemmo", 3306, NULL, 0);
if (NULL == conn_result)
{
cout << "DB Connection Fail" << endl;
}
else
{
cout << "DB Connection Success" << endl;
char query[1024];
MYSQL_RES* result{};
MYSQL_ROW row;
string id{ "test1" }, pw{ "1234" };
sprintf_s(query, 1024, "call dummytest('%s','%s',@param3)", id.c_str(), pw.c_str());
//Send Query
if (mysql_query(hmysql, query))
{
cout << "SELECT Fail" << endl;
fprintf(stderr, "Error %d\n%s", mysql_errno(hmysql), mysql_error(hmysql));
return;
}
mysql_free_result(result);
sprintf_s(query, 1024, "select @param3");
if (mysql_query(hmysql, query))
{
cout << "SELECT Fail" << endl;
fprintf(stderr, "Error %d\n%s", mysql_errno(hmysql), mysql_error(hmysql));
return;
}
result = mysql_store_result(hmysql);
MYSQL_FIELD* field;
field = mysql_fetch_fields(result);
int fields = mysql_num_fields(result); // 필드 갯수 구함
while (row = mysql_fetch_row(result)) // 모든 레코드 탐색 실패시 NULL반환 while 탈출
{
for (int i = 0; i < fields; i++) // 각각의 레코드에서 모든 필드 값 출력
{
cout << field[i].name<<":" << row[i] << " \n";
}
cout << endl;
}
mysql_free_result(result);
mysql_close(hmysql);
}