連接指定的埠口

下載 PHP 驅動程式

對於未明確指定連接埠的傳輸控制協定(TCP)連線,預設連接埠為 1433。 命名實例連線可使用 SQL Server 瀏覽器來發現實例的埠。 若要明確選擇 TCP 及特定埠口,請使用 tcp:<server>,<port>。 關於如何設定伺服器端的資訊,請參見 「設定伺服器監聽特定 TCP 埠」。

準備端點

  1. 請向伺服器管理員詢問主機名稱和 TCP 埠口。 客戶端的 連接字串 不會改變 SQL Server 監聽的埠口。
  2. 允許該埠通過伺服器防火牆及其間的網路控管設備。
  3. 只設定 SQL_SERVER 主機名稱、SQL_PORT 十進位連接埠號碼,以及 SQL_DATABASE 資料庫名稱。 這些程式會建構 tcp:<server>,<port>。 在連接埠前加逗號,不要加冒號。
  4. 透過受保護的處理程序設定,為這些 SQL 驗證範例設定 SQL_USER 和 SQL_PASSWORD。 若要使用整合或 Microsoft Entra 驗證,請使用 連線到伺服器 中的適當認證設定。

明確的埠碼可避免透過 SQL Server 瀏覽器進行實例埠偵測。 保持伺服器主機名稱與其憑證一致。 這兩個例子都不會禁用憑證驗證。

將實際的資料庫名稱、使用者名稱和密碼存入環境變數中。 兩個程式都會跳脫這些值一次,以實現 PHP 驅動程式類似 ODBC 的連線處理,方法是將右大括號重複一次,並將每個值用大括號括起來。 更多資訊請參見 「連接伺服器」。

SQLSRV

將此程式儲存為 connect-port-sqlsrv.php,並執行 php connect-port-sqlsrv.php。

<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_PORT', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name before running this example.");
    }
    $config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$port = filter_var($config['SQL_PORT'], FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 65535],
]);
if ($port === false) {
    throw new RuntimeException('SQL_PORT must be an integer from 1 through 65535.');
}
$serverName = 'tcp:' . $config['SQL_SERVER'] . ',' . $port;
$conn = sqlsrv_connect($serverName, [
    'Database' => $config['SQL_DATABASE'],
    'UID' => $config['SQL_USER'],
    'PWD' => $config['SQL_PASSWORD'],
    'Encrypt' => true,
    'TrustServerCertificate' => false,
    'LoginTimeout' => 30,
]);
if ($conn === false) {
    throw new RuntimeException(print_r(sqlsrv_errors(), true));
}
$stmt = null;
try {
    $stmt = sqlsrv_query($conn, 'SELECT CAST(1 AS int) AS Connected');
    if ($stmt === false) {
        throw new RuntimeException(print_r(sqlsrv_errors(), true));
    }
    $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
    if ($row === false) {
        throw new RuntimeException(print_r(sqlsrv_errors(), true));
    }
    if ($row !== ['Connected' => 1]) {
        throw new RuntimeException('Unexpected connection-test result.');
    }
    echo "Connected on TCP port $port.", PHP_EOL;
} finally {
    if (is_resource($stmt)) {
        sqlsrv_free_stmt($stmt);
    }
    sqlsrv_close($conn);
}

PDO_SQLSRV

將這個獨立程式儲存為 connect-port-pdo.php,並以相同的設定執行 php connect-port-pdo.php 。

<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_PORT', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name before running this example.");
    }
    $config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$port = filter_var($config['SQL_PORT'], FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 65535],
]);
if ($port === false) {
    throw new RuntimeException('SQL_PORT must be an integer from 1 through 65535.');
}
$serverName = 'tcp:' . $config['SQL_SERVER'] . ',' . $port;
$database = $config['SQL_DATABASE'];
$pdo = new PDO(
    "sqlsrv:Server=$serverName;Database=$database;Encrypt=true;"
    . "TrustServerCertificate=false;LoginTimeout=30",
    $config['SQL_USER'],
    $config['SQL_PASSWORD'],
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
$stmt = null;
try {
    $stmt = $pdo->query('SELECT CAST(1 AS int) AS Connected');
    if ($stmt->fetch(PDO::FETCH_ASSOC) !== ['Connected' => '1']) {
        throw new RuntimeException('Unexpected connection-test result.');
    }
    echo "Connected on TCP port $port.", PHP_EOL;
} finally {
    $stmt = null;
    $pdo = null;
}

對 SQL_PORT=1433 而言,其中一個程式會列印:

Connected on TCP port 1433.

擷取的 int 在 SQLSRV 中是 PHP int,在 PDO_SQLSRV 中預設是字串。 埠號是 SQLSRV 伺服器參數的一部分,也是 PDO_SQLSRV 的 DSN Server 關鍵字的一部分。 此模式中沒有獨立的 PDO Port 關鍵字。

疑難排解埠選擇

徵兆 Action
命名實例是可行的,但明確指定的連接埠不行 確認實際的監聽連接埠。 該實例可能使用重新啟動後變動的動態埠。
TCP 超時 檢查 PHP 主機的監聽器和防火牆。 開放埠仍無法證明 SQL 認證會成功。
使用 IP 位址後,憑證名稱驗證會失敗 使用憑證上的主機名稱和明確指定的連接埠。 不要為了名稱變更而關閉驗證功能。
應用程式仍能連接到其他位置 檢查執行中的 PHP 程序環境和產生的伺服器設定,但不要列印憑證。 如果設定需要,請重新啟動應用程式。

TCP 的選擇與實例發現屬於 ODBC 及伺服器的網路設定。 PHP 提供端點並回報連線結果。 對於 Azure SQL Database、Azure SQL 受控執行個體、Azure Synapse Analytics、Fabric 中的 SQL 資料庫,或 Fabric 中的 Warehouse,請保留服務提供的端點和埠,而非選擇任意埠。 SQL 登入程式並非任一 Fabric 產品的認證範例。 欲了解更多資訊,請參閱 Azure 與 Fabric 連線。