MySQLi 저장 프로시저
MySQL 데이터베이스는 저장 프로시저를 지원합니다. 저장 프로시저는 데이터베이스 카탈로그에 저장된 서브루틴입니다. 응용 프로그램은 저장 프로시저를 호출하고 실행할 수 있습니다. CALL SQL 문은 저장 프로시저를 실행하는 데 사용됩니다.
Parameter
저장 프로시저는 MySQL 버전에 따라 IN, INOUT 및 OUT 매개변수를 가질 수 있습니다. mysqli 인터페이스에는 다른 종류의 매개변수에 대한 특별한 개념이 없습니다.
IN parameter
입력 매개변수는 CALL 문과 함께 제공됩니다. 값이 올바르게 이스케이프되었는지 확인하십시오.
예제 #1 저장 프로시저 호출
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query("CREATE PROCEDURE p(IN id_val INT) BEGIN INSERT INTO test(id) VALUES(id_val); END;");
$mysqli->query("CALL p(1)");
$result = $mysqli->query("SELECT id FROM test");
var_dump($result->fetch_assoc());
위의 예는 다음을 출력합니다.
array(1) { ["id"]=> string(1) "1" }
INOUT/OUT parameter
INOUT/OUT 매개변수의 값은 세션 변수를 사용하여 액세스됩니다.
예제 #2 세션 변수 사용
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p(OUT msg VARCHAR(50)) BEGIN SELECT "Hi!" INTO msg; END;');
$mysqli->query("SET @msg = ''");
$mysqli->query("CALL p(@msg)");
$result = $mysqli->query("SELECT @msg as _p_out");
$row = $result->fetch_assoc();
echo $row['_p_out'];
위의 예는 다음을 출력합니다.
Hi!
애플리케이션 및 프레임워크 개발자는 세션 변수와 데이터베이스 카탈로그 검사를 함께 사용하여 보다 편리한 API를 제공할 수 있습니다. 그러나 카탈로그 검사를 기반으로 하는 맞춤형 솔루션이 성능에 미칠 수 있는 영향에 유의하십시오.
Handling result sets
저장 프로시저는 결과 집합을 반환할 수 있습니다. 저장 프로시저에서 반환된 결과 집합은 mysqli::query()를 사용하여 올바르게 가져올 수 없습니다. mysqli::query() 함수는 명령문 실행과 첫 번째 결과 세트를 버퍼링된 결과 세트(있는 경우)로 가져오는 것을 결합합니다. 그러나 mysqli::query()가 사용자가 예상한 결과 집합을 반환하지 못하게 하는 추가 저장 프로시저 결과 집합이 사용자에게 숨겨져 있습니다.
저장 프로시저에서 반환된 결과 집합은 mysqli::real_query() 또는 mysqli::multi_query()를 사용하여 가져옵니다. 두 함수 모두 CALL과 같은 명령문에서 반환된 결과 집합을 원하는 수만큼 가져올 수 있습니다. 저장 프로시저에서 반환된 모든 결과 집합을 가져오지 못하면 오류가 발생합니다.
예제 #3 저장 프로시저에서 결과 가져오기
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');
$mysqli->multi_query("CALL p()");
do {
if ($result = $mysqli->store_result()) {
printf("---\n");
var_dump($result->fetch_all());
$result->free();
}
} while ($mysqli->next_result());
위의 예는 다음을 출력합니다.
--- array(3) { [0]=> array(1) { [0]=> string(1) "1" } [1]=> array(1) { [0]=> string(1) "2" } [2]=> array(1) { [0]=> string(1) "3" } } --- array(3) { [0]=> array(1) { [0]=> string(1) "2" } [1]=> array(1) { [0]=> string(1) "3" } [2]=> array(1) { [0]=> string(1) "4" } }
준비된 명령문의 사용
위와 동일한 저장 프로시저에서 결과를 가져오기 위해 준비된 명령문 인터페이스를 사용할 때 특별한 처리가 필요하지 않습니다. 준비된 명령문과 준비되지 않은 명령문 인터페이스는 비슷합니다. 모든 MYSQL 서버 버전이 CALL SQL 문 준비를 지원하는 것은 아닙니다.
예제 #4 저장 프로시저 및 준비된 명령문
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');
$stmt = $mysqli->prepare("CALL p()");
$stmt->execute();
do {
if ($result = $stmt->get_result()) {
printf("---\n");
var_dump($result->fetch_all());
$result->free();
}
} while ($stmt->next_result());
위의 예는 다음을 출력합니다.
--- array(3) { [0]=> array(1) { [0]=> int(1) } [1]=> array(1) { [0]=> int(2) } [2]=> array(1) { [0]=> int(3) } } --- array(3) { [0]=> array(1) { [0]=> int(2) } [1]=> array(1) { [0]=> int(3) } [2]=> array(1) { [0]=> int(4) } }
물론 fetch를 위한 bind API도 지원합니다.
예제 #5 바인드 API를 사용한 저장 프로시저 및 준비된 명령문
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("example.com", "user", "password", "database");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
$mysqli->query("DROP PROCEDURE IF EXISTS p");
$mysqli->query('CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id FROM test; SELECT id + 1 FROM test; END;');
$stmt = $mysqli->prepare("CALL p()");
$stmt->execute();
do {
if ($stmt->store_result()) {
$stmt->bind_result($id_out);
while ($stmt->fetch()) {
echo "id = $id_out\n";
}
}
} while ($stmt->next_result());
위의 예는 다음을 출력합니다.
id = 1 id = 2 id = 3 id = 2 id = 3 id = 4