首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

PHP 調用 SQL Server 存儲過程:輸出參數與返回值完整實戰

     編輯:MySQL 資料庫相關知識

前言

PHP 透過 mssql(舊)或 sqlsrv/PDO_SQLSRV(現代)擴展調用 SQL Server 存儲過程時,處理輸出參數與返回值是常見痛點。本文以實戰代碼演示完整調用流程,並給出現代化遷移建議。

一、舊版 mssql 擴展範例(僅供維護舊專案參考)

<?php
$hostname = 'tszzp';
$dbuser   = 'sa';
$dbpasswd = '';
$dbname   = 'stock';

$conn = mssql_connect($hostname, $dbuser, $dbpasswd) or die('無法連接服務器');
mssql_select_db($dbname, $conn) or die('無法選擇資料庫');

$stockcode = '600600';

// 構建 T-SQL 批次:宣告變數、執行存儲過程、選取輸出
$query = "DECLARE @result INT, @id INT, @msg VARCHAR(20);
          EXEC @result = sp_test '$stockcode', @id OUTPUT, @msg OUTPUT;
          SELECT @result AS result, @id AS id, @msg AS msg;";

$rs = mssql_query($query, $conn) or die('SQL 執行失敗: ' . $query);
$row = mssql_fetch_assoc($rs);

echo "Result: {$row['result']}<br>";
echo "ID: {$row['id']}, Msg: {$row['msg']}<br>";

mssql_free_result($rs);
mssql_close($conn);
?>

關鍵點:

  • 使用 DECLARE ... EXEC @return = proc ... OUTPUT ... SELECT @vars 批次包裝。
  • 輸出參數需在 EXEC 時指定 OUTPUT,並在後續 SELECT 取回。
  • mssql_fetch_assoc 直接以欄位名取值,避免數字索引易誤。

二、現代化方案:PDO_SQLSRV (PHP 7.2+ / SQL Server 2012+)

強烈建議新專案使用 PDO_SQLSRV,支援預處理、參數綁定、異常處理,代碼更安全優雅。

<?php
$serverName = 'tszzp';
$connStr = "sqlsrv:Server=$serverName;Database=stock";
$user = 'sa'; $pass = '';

try {
    $pdo = new PDO($connStr, $user, $pass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    ]);

    $stockcode = '600600';
    $id = 0; $msg = '';

    // 預處理語句:? 佔位符對應參數順序
    $stmt = $pdo->prepare('EXEC sp_test @code = ?, @id = ?, @msg = ?');
    // 綁定輸出參數:PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT
    $stmt->bindParam(1, $stockcode, PDO::PARAM_STR);
    $stmt->bindParam(2, $id, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 20);
    $stmt->bindParam(3, $msg, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 20);

    $stmt->execute();

    // 取得返回值(SQL Server 存儲過程 RETURN 值)
    $returnValue = $stmt->fetchColumn(); // 若存儲過程有 SELECT 結果集,需先處理結果集
    // 更穩健:使用 SQLSRV 驅動專屬函數 sqlsrv_next_result() 切換結果集

    echo "Return: $returnValue<br>";
    echo "Output ID: $id, Msg: $msg<br>";

} catch (PDOException $e) {
    die('錯誤: ' . $e->getMessage());
}
?>

三、存儲過程範例 (sp_test)

CREATE PROCEDURE sp_test
    @code VARCHAR(20),
    @id INT OUTPUT,
    @msg VARCHAR(20) OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    -- 業務邏輯...
    SET @id = 12345;
    SET @msg = 'SUCCESS';
    RETURN 0;  -- 返回值
END

四、常見坑點與避雷指南

坑點解決方案
多結果集導致輸出參數讀不到PDO: $stmt->nextRowset() 切換;sqlsrv: sqlsrv_next_result()
OUTPUT 參數未指定長度導致截斷bindParam 第 4 參數指定最大長度
舊 mssql 擴展 PHP 7+ 已移除強制遷移至 sqlsrv / PDO_SQLSRV
字符集亂碼連接字串加 CharacterSet=UTF-8,資料庫欄位用 NVARCHAR

五、總結

PHP 調用 SQL Server 存儲過程的核心在於:批次包裝輸出參數(舊版)或預處理綁定 INPUT_OUTPUT 參數(現代版)。新專務必使用 PDO_SQLSRV,配合嚴格錯誤模式與參數化查詢,徹底解決注入、編碼、資源洩漏等歷史問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved