前置準備
<?php
$conn = mysqli_connect('localhost', 'user', 'pass', 'db');
mysqli_set_charset($conn, 'utf8mb4');
?>
類型一:單一輸出參數
<?php
$returnValue = '';
mysqli_query($conn, "SET @Return = 0");
mysqli_query($conn, "CALL P__Test_GetInfo1(@Return, 'user1', 'pwd')") or die(mysqli_error($conn));
$res = mysqli_query($conn, "SELECT @Return");
$row = mysqli_fetch_row($res);
$returnValue = $row[0];
echo $returnValue; // 輸出參數值
?>
類型二:多輸入/輸出參數
<?php
$userId = 0;
mysqli_query($conn, "SET @Message = '', @Id = 0");
mysqli_query($conn, "CALL P__Test_Login(@Message, @Id, 'user1', 'pwd')") or die(mysqli_error($conn));
$msg = mysqli_fetch_row(mysqli_query($conn, "SELECT @Message"))[0];
$uid = mysqli_fetch_row(mysqli_query($conn, "SELECT @Id"))[0];
echo "Message: $msg\nUser ID: $uid";
類型三:單一結果集
<?php
$res = mysqli_query($conn, "CALL P__Test_GetData()") or die(mysqli_error($conn));
while ($row = mysqli_fetch_assoc($res)) {
echo $row['ProvinceID'] . '::' . $row['ProvinceName'] . "\n";
}
mysqli_free_result($res);
類型四:多結果集(需 mysqli)
<?php
$db = new mysqli('localhost', 'user', 'pass', 'db');
$db->query('SET NAMES utf8mb4');
$db->query('SET @Message = ""');
$rows = [];
if ($db->real_query('CALL P__Test_GetData2(@Message)')) {
do {
if ($result = $db->store_result()) {
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
$result->close();
}
} while ($db->next_result());
}
$db->close();
print_r($rows);
對應預存程序骨架
-- 類型四:多結果集
CREATE PROCEDURE P__Test_GetData2(OUT p_msg VARCHAR(255))
BEGIN
SET p_msg = 'OK';
SELECT * FROM T1 WHERE ...;
SELECT * FROM T2 WHERE ...;
-- 可繼續多個 SELECT
END
關鍵差異表
| 類型 | 關鍵函數 | 適用場景 |
| 輸出參數 | SET @var / SELECT @var | 狀態碼、訊息、單一值 |
| 單結果集 | mysqli_query + fetch | 一般查詢 |
| 多結果集 | mysqli::real_query + next_result() | 一支 SP 回傳多張表 |
遷移建議
- 全面改用
mysqli 或 PDO,mysql_* 已移除(PHP 7+)
- 使用 Prepared Statements 防注入:
$stmt = $db->prepare('CALL sp(?, ?)')
- 多結果集僅
mysqli 原生支援,PDO 需用 PDO::nextRowset()(驅動支援度不一)