ストアドプロシージャの呼び出しは、PHPを使用してMySQLデータベースを操作する場合、特にデータベースレベルで複雑なビジネスロジックをカプセル化する場合によく見られます。ただし、多くの開発者は、**出力パラメーター(outパラメーター)を使用してストアドプロシージャを呼び出すときに出力パラメーター値を読み取れない状況に遭遇することがよくあります。
重要なポイントの1つは、next_result()の使用です。この記事では、この関数を呼び出す必要がある理由と、ストアドプロシージャの出力パラメーターを正しく読み取る方法を詳細に説明します。
MySQLIドライバーを使用して、複数の結果セット(複数の選択または両方の選択パラメーターと出力パラメーターなど)を返すストアドプロシージャを呼び出す場合、MySQLは「複数の結果セット」の形式でデータを返します。 next_result()メソッドは、 mysqliドライバーに次の結果セットを読み取る準備をするために使用されます。
next_result()が明示的に呼び出されず、すべての結果セットがトラバースされている場合、一部のデータベース結果(出力パラメーターや最終結果セットなど)にアクセスできません。
まず、入力パラメーターと出力パラメーターを備えた単純なMySQLストアドプロシージャを見てみましょう。
DELIMITER $$
CREATE PROCEDURE get_user_email(IN user_id INT, OUT email VARCHAR(255))
BEGIN
SELECT user_email INTO email FROM users WHERE id = user_id;
END $$
DELIMITER ;
このストアドプロシージャは、ユーザーIDに基づいてメールボックスを照会し、OUTパラメーターから返します。
<?php
$mysqli = new mysqli("localhost", "username", "password", "your_database");
// 接続を確認してください
if ($mysqli->connect_error) {
die("接続に失敗しました: " . $mysqli->connect_error);
}
// 1. 設定 OUT パラメーター変数
$mysqli->query("SET @email = ''");
// 2. ストアドプロシージャを呼び出します
$mysqli->query("CALL get_user_email(1, @email)");
// 3. 使用する必要があります next_result() 結果セットをクリアします
while ($mysqli->more_results()) {
$mysqli->next_result();
$result = $mysqli->store_result();
if ($result) {
$result->free();
}
}
// 4. 得る OUT パラメーター
$result = $mysqli->query("SELECT @email AS user_email");
$row = $result->fetch_assoc();
echo "ユーザーのメールアドレスはです: " . $row['user_email'];
$mysqli->close();
?>
コールステートメントを呼び出した後、MySQLは実際に1つ以上の暗黙の結果セットを返すことができます。 next_result()がこれらの結果セットをクリアするために使用されない場合、その後のクエリ( Select @Emailなど)がブロックまたは実行に失敗する場合があります。
一部の開発者は、「読み取り出力パラメーターが空です」という問題に遭遇します。実際、ストアドプロシージャが正常に実行されていないということではなく、前の結果セットがクリアされておらず、その後のクエリがまったく実行されないことです。
前処理ステートメントを使用している場合は、同様のロジックを使用することもできます。
$stmt = $mysqli->prepare("CALL get_user_email(?, @email)");
$stmt->bind_param("i", $userId);
$userId = 1;
$stmt->execute();
// すべての結果セットをクリーンアップします
do {
if ($result = $stmt->get_result()) {
$result->free();
}
} while ($stmt->more_results() && $stmt->next_result());
// 得る输出パラメーター
$result = $mysqli->query("SELECT @email AS user_email");
$row = $result->fetch_assoc();
echo "ユーザーのメールアドレスはです: " . $row['user_email'];
コールを使用してストアドプロシージャを実行する場合は、 next_result()を呼び出して、出力パラメーターが使用されているか、複数の結果セットが返されているかに関係なく、すべての潜在的な結果セットを繰り返してください。
これは良い習慣であるだけでなく、OUTパラメーターを正しく読み取ることができるようにするための前提条件でもあります。これを念頭に置いておくと、「結果が読まれていない」という問題の頭痛を避けるのに役立ちます。
ストアドプロシージャコールのベストプラクティスについては、開発ガイドhttps://gitbox.net/docs/mysql/stored-proceduresにアクセスできます。