디폴트로, mysql_query() 및 mysql_real_query()는 자신들의 명령문 스트링 인수를 실행해야 하는 싱글 명령문으로 해석한다.
MySQL 5.1은 세미콜론 (‘;’) 문자로 구분된 멀티 명령문이 있는 스트링 실행도 지원한다. 이 기능은 mysql_real_connect()를 사용해서 서버에 연결할 때 또는 mysql_set_server_option()를 호출해서 서버에 연결한 후에 지정하는 특별 옵션을 가지고 활성화 시킬 수가 있다.
멀티-명령문 스트링 실행은 멀티 결과 셋 또는 열-카운트 인디케이터를 생성한다. 이러한 결과를 처리할 때에는 싱글 명령문을 처리하는 것과 다른 방식의 접근이 필요하다: 첫 번째 명령문의 결과를 처리한 후에는 다른 결과가 아직 존재하는지를 검사해야 하고 만약에 존재한다면 그것을 처리해야 한다. 멀티-결과 프로세싱을 지원하기 위해서 C API에는 mysql_more_results() 및 mysql_next_result() 함수가 포함되어 있다. 일반적으로, 이러한 함수들은 루프의 맨 마지막에 사용된다.
스토어드 프로시저용으로 CALL 명령문을 실행하는 경우에도 멀티-결과 프로세싱이 필요하다: 스토어드 프로시저는 실행을 종료할 때 상태 결과를 리턴하지만, 구동된 결과 셋도 함께 생성한다. 마지막 상태 결과와 함께 결과 셋을 생성하는 모든 스토어드 프로시저에 대해서는 반드시 여러 개의 결과를 추출할 준비를 해야 한다.
멀티 명령문 및 멀티 결과 기능은 오직 mysql_query() 또는 mysql_real_query()와 함께 사용할 수가 있다. 이러한 함수들은 프리페어드 명령문 인터페이스와 함께 사용할 수가 없다. 프리페어드 명령문 핸들은 오직 싱글 명령문을 가지고 있는 스트링과 함께 사용되도록 정의된다.
멀티-명령문 실행 및 결과 프로세싱을 활성화 하기 위해서 아래의 옵션들이 사용될 수도 있다:
- mysql_real_connect() 함수는 두 개의 옵션이 연관되어 있는 flags 인수를 가지고 있다:
- CLIENT_MULTI_RESULTS는 클라이언트 프로그램이 멀티 결과를 처리할 수 있도록 만든다. 결과 셋을 생성하는 스토어드 프로시저용으로 CALL 명령문을 실행하는 경우에는 반드시 이 옵션을 활성화 시켜야 한다. 그렇지 않으면, Error 1312 (0A000): PROCEDURE proc_name can't return a result set in the given context라는 에러가 발생한다.
- CLIENT_MULTI_STATEMENTS는 mysql_query() 및 mysql_real_query()가 세미콜론으로 구분된 멀티 명령문을 가지고 있는 명령문 스트링을 실행하도록 만든다. 이 옵션은 CLIENT_MULTI_RESULTS도 활성화 시키기 때문에, mysql_real_connect()에 대한 CLIENT_MULTI_STATEMENTS의 flags 인수는 CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS의 인수와 같은 것이 된다. 즉, CLIENT_MULTI_STATEMENTS 함수만 사용하더라도 멀티-명령문 실행과 모든 멀티-결과 프로세싱을 처리할 수가 있다.
- 서버에 대한 연결이 구축된 후에는 mysql_set_server_option() 함수를 사용해서 멀티-명령문 실행을 활성화 또는 비활성화 시킬 수가 있다.
아래의 과정은 멀티-명령문 처리를 실행하는 방법을 설명하는 것이다:
1. CLIENT_MULTI_STATEMENTS를 mysql_real_connect()에 전달해서 멀티-명령문 실행과 멀티-결과 프로세싱을 전체적으로 활성화 시킨다.
2. mysql_query() 또는 mysql_real_query()를 호출한 후에, 실행 중인 명령문 결과에 루프를 입력한다.
3. 루프를 반복적으로 실행할 때마다 현재의 명령문 결과를 처리하고, 결과 셋 또는 영향을 받은 열 카운드를 추출한다. 에러가 발생한다면, 루프가 종료한다.
4. 루프의 마지막에서 mysql_next_result()를 호출해서 다른 결과 셋이 남아 있는지를 검사한 후에 남아 있다면 그것을 추출한다. 더 이상 결과가 남아 있지 않다면, 루프를 종료한다.
다음 예문을 보도록 한다.
/* connect to server with option CLIENT_MULTI_STATEMENTS */
if (mysql_real_connect (mysql, host_name, user_name, password,
db_name, port_num, socket_name, CLIENT_MULTI_STATEMENTS) == NULL)
{
printf("mysql_real_connect() failed\n");
mysql_close(mysql);
exit(1);
}
/* execute multiple statements */
status = mysql_query(mysql,
"DROP TABLE IF EXISTS test_table;\
CREATE TABLE test_table(id INT);\
INSERT INTO test_table VALUES(10);\
UPDATE test_table SET id=20 WHERE id=10;\
SELECT * FROM test_table;\
DROP TABLE test_table");
if (status)
{
printf("Could not execute statement(s)");
mysql_close(mysql);
exit(0);
}
/* process each statement result */
do {
/* did current statement return data? */
result = mysql_store_result(mysql);
if (result)
{
/* yes; process rows and free the result set */
process_result_set(mysql, result);
mysql_free_result(result);
}
else /* no result set or error */
{
if (mysql_field_count(mysql) == 0)
{
printf("%lld rows affected\n",
mysql_affected_rows(mysql));
}
else /* some error occurred */
{
printf("Could not retrieve result set\n");
break;
}
}
/* more results? -1 = no, >0 = error, 0 = yes (keep looping) */
if ((status = mysql_next_result(mysql)) > 0)
printf("Could not execute statement\n");
} while (status == 0);
mysql_close(mysql);