首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 調用 MySQL 存儲過程並獲取返回值:mysqli/PDO 完整實戰指南

     編輯:PHP 相關知識

存儲過程定義示例

DELIMITER //

CREATE PROCEDURE `sp_get_employee_list`(
    IN  p_dept_id     INT,
    OUT p_total_count INT
)
BEGIN
    SELECT COUNT(*) INTO p_total_count FROM employees WHERE dept_id = p_dept_id;
    
    SELECT id, name, salary, hire_date 
    FROM employees 
    WHERE dept_id = p_dept_id 
    ORDER BY hire_date DESC;
END //

DELIMITER ;

mysqli 面向對象調用

<?php
$mysqli = new mysqli("localhost", "root", "pass", "company");
$mysqli->set_charset("utf8mb4");

$deptId = 10;

// 1. 調用存儲過程(多結果集:第一個是 OUT 參數 SELECT,第二個是業務數據)
$sql = "CALL sp_get_employee_list($deptId, @total)";

if ($mysqli->multi_query($sql)) {
    // 結果集 1:OUT 參數(這裡通過 SELECT @total 獲取)
    do {
        if ($result = $mysqli->store_result()) {
            // 業務數據結果集
            while ($row = $result->fetch_assoc()) {
                echo "ID: {$row['id']}, Name: {$row['name']}, Salary: {$row['salary']}
"; } $result->free(); } } while ($mysqli->more_results() && $mysqli->next_result()); // 獲取 OUT 參數值 $outResult = $mysqli->query("SELECT @total AS total_count"); $outRow = $outResult->fetch_assoc(); echo "部門總人數: " . $outRow['total_count']; $outResult->free(); } else { echo "調用失敗: " . $mysqli->error; } $mysqli->close();

PDO 調用(推薦,參數綁定更安全)

<?php
$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false, // 真實預處理
]);

$deptId = 10;

// 1. 註冊 OUT 參數
$stmt = $pdo->prepare("CALL sp_get_employee_list(:dept_id, @total_count)");
$stmt->bindParam(':dept_id', $deptId, PDO::PARAM_INT);
$stmt->execute();

// 2. 獲取業務結果集
do {
    if ($stmt->columnCount() > 0) { // 有列信息說明是數據結果集
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            print_r($row);
        }
    }
} while ($stmt->nextRowset());

// 3. 獲取 OUT 參數
$outStmt = $pdo->query("SELECT @total_count AS total");
$total = $outStmt->fetchColumn();
echo "總記錄數: $total";

僅有 OUT/INOUT 參數的簡化調用

-- 存儲過程
CREATE PROCEDURE sp_calc_bonus(
    IN  p_emp_id   INT,
    IN  p_rate     DECIMAL(5,2),
    OUT p_bonus    DECIMAL(10,2)
)
BEGIN
    SELECT salary * p_rate INTO p_bonus FROM employees WHERE id = p_emp_id;
END;

-- PHP (mysqli)
$mysqli->query("SET @bonus = 0");
$mysqli->query("CALL sp_calc_bonus(101, 0.15, @bonus)");
$res = $mysqli->query("SELECT @bonus AS bonus");
$bonus = $res->fetch_assoc()['bonus'];
echo "獎金: $bonus";

參數類型對應表

MySQL 類型PDO::PARAM_*mysqli 綁定類型
INT / BIGINTPARAM_INT'i'
VARCHAR / TEXTPARAM_STR's'
DECIMAL / FLOATPARAM_STR'd'
DATE / DATETIMEPARAM_STR's'
BOOL / TINYINT(1)PARAM_BOOL'i'
BLOB / BINARYPARAM_LOB'b'

常見錯誤與解決

錯誤原因解決
PROCEDURE ... can't return a result setmysqli 默認不支持存儲過程返回結果集啟用 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) 或使用 multi_query
Commands out of sync未處理完所有結果集循環 next_result() 直到 false
OUT 參數為 NULL未在 SQL 中聲明用戶變量 @xxx調用前 SET @out = 0,調用後 SELECT @out
參數綁定失效PDO::ATTR_EMULATE_PREPARES = true設置 false 使用真實預處理

最佳實踐建議

  1. 業務邏輯下沉存儲過程:複雜事務、批量計算、報表統計適合;簡單 CRUD 保持在應用層。
  2. 版本控制:存儲過程代碼納入 Git,遷移腳本管理。
  3. 權限最小化:應用用戶僅授予 EXECUTE 權限,無直接表操作權限。
  4. 參數化防注入:嚴禁拼接 CALL 語句,全部使用預處理綁定。
  5. 結果集處理:預期可能有多結果集,統一用 multi_query / nextRowset() 循環處理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved