23.8.20 C API의 Prepared CALL Statements 지원
이 섹션에서는 CALL
문을 사용하여 실행되는 저장 프로 시저에 대한 C API의 프리 페 아드 스테이트먼트의 지원에 대해 설명합니다.
MySQL 5.6에서는 Prepared CALL
Statements을 사용하여 실행되는 저장 프로 시저를 다음과 같이 사용할 수 있습니다.
저장 프로 시저는 임의의 수의 결과 세트를 생성 할 수 있습니다. 컬럼의 수와 컬럼의 데이터 유형은 모든 결과 세트에 대해 동일 할 필요는 없습니다.
OUT
및INOUT
파라미터의 최종 값은 프로 시저가 돌아온 뒤에 호출 응용 프로그램에서 사용할 수 있습니다. 이러한 매개 변수는 프로 시저 자체에 의해 생성 된 결과 집합에 이어 특별한 단일 행 결과 집합으로 반환됩니다. 행에는OUT
및INOUT
매개 변수가 프로 시저 매개 변수 목록에서 선언 된 순서대로 포함됩니다.
다음의 설명에 Prepared Statement에 대해 C API에서 이러한 기능을 사용하는 방법을 보여줍니다. PREPARE
및 EXECUTE
문에서 Prepared CALL
문을 사용하려면 섹션 13.2.1 "CALL 구문" 을 참조하십시오.
응용 프로그램이 5.5.3 이전의 MySQL 버전이 사용 된 문맥으로 컴파일 또는 실행되고있을 가능성이있는 경우 여러 결과 세트의 Prepared CALL
기능 및 OUT
또는 INOUT
매개 변수를 사용하지 못할 수 있습니다.
클라이언트 측 라이브러리가 MySQL 5.5.3 이상하지 않으면, 응용 프로그램은 컴파일되지 않습니다 (버전에서 도입 된 API 함수 및 기호가 존재하지 않습니다).
서버가 완전히 새로운 것을 실행시 확인하려면 클라이언트에서이 테스트를 사용할 수 있습니다.
if (mysql_get_server_version(mysql) < 50503) { fprintf(stderr, "Server does not support required CALL capabilities\n"); mysql_close(mysql); exit (1); }
Prepared CALL
문을 실행하는 응용 프로그램은 결과를 가져 와서 다음 mysql_stmt_next_result()
를 호출 해, 그 이상의 결과가 있는지를 판단하는 루프를 사용하십시오. 결과는 저장 프로 시저에 의해 생성 된 결과 세트와 거기에 계속되는 시저가 성공적으로 완료되었는지 여부를 나타내는 최종 상태 값으로 구성됩니다.
프로 시저에 OUT
또는 INOUT
매개 변수가있는 경우 최종 상태 값 이전 결과 세트에 그 값이 저장됩니다. 결과 세트 매개 변수 값이 저장되어 있는지를 판단하려면 MYSQL
연결 처리기의 server_status
멤버에 SERVER_PS_OUT_PARAMS
비트가 설정되어 있는지 여부를 테스트합니다.
mysql->server_status & SERVER_PS_OUT_PARAMS
다음 예제에서는 Prepared CALL
문을 사용하여 여러 결과 집합을 생성하여 OUT
및 INOUT
매개 변수를 사용하여 호출에 매개 변수 값을 반환하는 저장 프로 시저를 실행하고 있습니다. 시저는 세 가지 형태 ( IN
, OUT
, INOUT
)의 매개 변수를 취하여 그 초기 값을 표시하고 새 값을 할당 업데이트 된 값을 표시하고 돌아갑니다. 따라서 프로 시저에서 예상되는 리턴 정보는 여러 결과 세트와 최종 상태에서 구성됩니다.
초기 파라미터 값 (
10
,NULL
,30
)를 표시하는SELECT
에서 하나의 결과 집합. (OUT
매개 변수는 호출자가 값이 할당되지만이 할당 해제 될 것으로 예상됩니다.OUT
매개 변수는 프로 시저에서 값을 할당하기 전까지 프로 시저에서NULL
로 간주됩니다.)변경된 매개 변수 값 (
100
,200
,300
)를 표시하는SELECT
에서 하나의 결과 집합.최종
OUT
및INOUT
매개 변수 값 (200
,300
)를 포함하는 1 개의 결과 세트.최종 상태 패킷.
프로 시저를 실행하는 코드 :
MYSQL_STMT *stmt; MYSQL_BIND ps_params[3]; /* input parameter buffers */ int int_data[3]; /* input/output values */ my_bool is_null[3]; /* output value nullability */ int status; /* set up stored procedure */ status = mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1"); test_error(mysql, status); status = mysql_query(mysql, "CREATE PROCEDURE p1(" " IN p_in INT, " " OUT p_out INT, " " INOUT p_inout INT) " "BEGIN " " SELECT p_in, p_out, p_inout; " " SET p_in = 100, p_out = 200, p_inout = 300; " " SELECT p_in, p_out, p_inout; " "END"); test_error(mysql, status); /* initialize and prepare CALL statement with parameter placeholders */ stmt = mysql_stmt_init(mysql); if (!stmt) { printf("Could not initialize statement\n"); exit(1); } status = mysql_stmt_prepare(stmt, "CALL p1(?, ?, ?)", 16); test_stmt_error(stmt, status); /* initialize parameters: p_in, p_out, p_inout (all INT) */ memset(ps_params, 0, sizeof (ps_params)); ps_params[0].buffer_type = MYSQL_TYPE_LONG; ps_params[0].buffer = (char *) &int_data[0]; ps_params[0].length = 0; ps_params[0].is_null = 0; ps_params[1].buffer_type = MYSQL_TYPE_LONG; ps_params[1].buffer = (char *) &int_data[1]; ps_params[1].length = 0; ps_params[1].is_null = 0; ps_params[2].buffer_type = MYSQL_TYPE_LONG; ps_params[2].buffer = (char *) &int_data[2]; ps_params[2].length = 0; ps_params[2].is_null = 0; /* bind parameters */ status = mysql_stmt_bind_param(stmt, ps_params); test_stmt_error(stmt, status); /* assign values to parameters and execute statement */ int_data[0]= 10; /* p_in */ int_data[1]= 20; /* p_out */ int_data[2]= 30; /* p_inout */ status = mysql_stmt_execute(stmt); test_stmt_error(stmt, status); /* process results until there are no more */ do { int i; int num_fields; /* number of columns in result */ MYSQL_FIELD *fields; /* for result set metadata */ MYSQL_BIND *rs_bind; /* for output buffers */ /* the column count is > 0 if there is a result set */ /* 0 if the result is only the final status packet */ num_fields = mysql_stmt_field_count(stmt); if (num_fields > 0) { /* there is a result set to fetch */ printf("Number of columns in result: %d\n", (int) num_fields); /* what kind of result set is this? */ printf("Data: "); if(mysql->server_status & SERVER_PS_OUT_PARAMS) printf("this result set contains OUT/INOUT parameters\n"); else printf("this result set is produced by the procedure\n"); MYSQL_RES *rs_metadata = mysql_stmt_result_metadata(stmt); test_stmt_error(stmt, rs_metadata == NULL); fields = mysql_fetch_fields(rs_metadata); rs_bind = (MYSQL_BIND *) malloc(sizeof (MYSQL_BIND) * num_fields); if (!rs_bind) { printf("Cannot allocate output buffers\n"); exit(1); } memset(rs_bind, 0, sizeof (MYSQL_BIND) * num_fields); /* set up and bind result set output buffers */ for (i = 0; i < num_fields; ++i) { rs_bind[i].buffer_type = fields[i].type; rs_bind[i].is_null = &is_null[i]; switch (fields[i].type) { case MYSQL_TYPE_LONG: rs_bind[i].buffer = (char *) &(int_data[i]); rs_bind[i].buffer_length = sizeof (int_data); break; default: fprintf(stderr, "ERROR: unexpected type: %d.\n", fields[i].type); exit(1); } } status = mysql_stmt_bind_result(stmt, rs_bind); test_stmt_error(stmt, status); /* fetch and display result set rows */ while (1) { status = mysql_stmt_fetch(stmt); if (status == 1 || status == MYSQL_NO_DATA) break; for (i = 0; i < num_fields; ++i) { switch (rs_bind[i].buffer_type) { case MYSQL_TYPE_LONG: if (*rs_bind[i].is_null) printf(" val[%d] = NULL;", i); else printf(" val[%d] = %ld;", i, (long) *((int *) rs_bind[i].buffer)); break; default: printf(" unexpected type (%d)\n", rs_bind[i].buffer_type); } } printf("\n"); } mysql_free_result(rs_metadata); /* free metadata */ free(rs_bind); /* free output buffers */ } else { /* no columns = final status packet */ printf("End of procedure output\n"); } /* more results? -1 = no, >0 = error, 0 = yes (keep looking) */ status = mysql_stmt_next_result(stmt); if (status > 0) test_stmt_error(stmt, status); } while (status == 0); mysql_stmt_close(stmt);
프로 시저를 실행하면 다음과 같은 출력이 생성됩니다.
Number of columns in result: 3 Data: this result set is produced by the procedure val[0] = 10; val[1] = NULL; val[2] = 30; Number of columns in result: 3 Data: this result set is produced by the procedure val[0] = 100; val[1] = 200; val[2] = 300; Number of columns in result: 2 Data: this result set contains OUT/INOUT parameters val[0] = 200; val[1] = 300; End of procedure output
이 코드는 두 개의 유틸리티 루틴 test_error()
및 test_stmt_error()
를 사용하여 오류를 확인하고 오류가 발생한 경우 진단 정보를 출력 한 후에 종료합니다.
static void test_error(MYSQL *mysql, int status) { if (status) { fprintf(stderr, "Error: %s (errno: %d)\n", mysql_error(mysql), mysql_errno(mysql)); exit(1); } } static void test_stmt_error(MYSQL_STMT *stmt, int status) { if (status) { fprintf(stderr, "Error: %s (errno: %d)\n", mysql_stmt_error(stmt), mysql_stmt_errno(stmt)); exit(1); } }