기존의 stored procedure가 실행이 잘 안되어서 일반적인 쿼리문으로 짜려고 했는데 

 

안되던 이유를 찾음.

 

https://dev.mysql.com/doc/c-api/5.7/en/c-api-multiple-queries.html

 

MySQL :: MySQL 5.7 C API Developer Guide :: 3.6.2 Multiple Statement Execution Support

3.6.2 Multiple Statement Execution Support By default, mysql_real_query() and mysql_query() interpret their statement string argument as a single statement to be executed, and you process the result according to whether the statement produces a result set

dev.mysql.com

 

내가 이해한 내용으로 적자면 

 

저장프로시저는 결과집합을 생성할 수 있으므로, 한 번 결과를 캐는게 끝났다면 

 

mysql_next_result()를 호출하여 (prepare statement에서는 mysql_stmt_next_result())

결과집합이 있는지 확인해야 한다는 것이었다.

 

그리고 이 함수를 사용하려면 mysql_connect 할 때 마지막인자에 CLIENT_MULTI_STATEMENTS 를 넣어 다중결과처리를 활성화 해야한다는 얘기 또한 있다,,

 

그동안 저장프로시저를 사용해서 select문을 실행하면 계속 syntax error가 떴던 것,,,,

prepare statement에도 똑같이 에러가 떳었는데 이것 또한 이때문이었던 것 같다 '-'....

 

고쳐서 코딩 결과 제대로 실행되는 것을 확인. 

 

다만 mysql_next_result()를 써서 결과집합이 또 있는지 체크해야하는거 때문에 코드가 길어지는 건 어쩔 수 없는듯 하다. 

또한 이것에 저장프로시저의 OUT 인자도 사용법이 애매했었는데 

 

https://dev.mysql.com/doc/c-api/5.7/en/c-api-prepared-call-statements.html

 

여기 설명이 친절하게 나와있다.. 예시랑 ^^...

검색을 잘 해보도록 하자 ! 

'개발 > MySQL' 카테고리의 다른 글

Mysql C++에서 Stored Procedure OUT 인자 사용하기.  (0) 2023.03.26

개요

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);
	}

 

'개발 > MySQL' 카테고리의 다른 글

mysql에서 stored procedure를 사용하는 방법.  (0) 2023.04.01

+ Recent posts