1 回答

TA貢獻1802條經驗 獲得超4個贊
說明:
提供的解決方案的一部分是以下解釋:
似乎在執行大量 SQL 語句時,Microsoft SQL Server 可能會在執行批處理中的所有語句之前停止處理該批處理。處理批處理的結果時,SQL Server 使用批處理創建的結果集填充連接的輸出緩沖區。這些結果集必須由客戶端應用程序處理。如果您正在執行具有多個結果集的大型批處理,SQL Server 會填充該輸出緩沖區,直到它達到內部限制并且無法繼續處理更多結果集。那時,控制權返回給客戶端。此行為是設計使然??蛻舳藨贸绦驊⑿滤写幚淼慕Y果集。一旦所有掛起的結果集都被客戶端使用,SQL Server 就會完成批處理的執行??蛻舳藨贸绦蚩梢哉{用 sqlsrv_next_result() 直到它返回 NULL。
因此,我認為 SQL 語句的長度沒有限制,只有 PHP 字符串變量($InsertSQL
在您的情況下)的大小被限制為允許的最大 PHP 內存限制。這種意外行為的實際原因是,對于SET NOCOUNT OFF
(默認情況下)和大量的單個INSERT
語句,SQL Server 將受影響的行數作為結果集返回(例如(1 row affected)
)。
解決方案:
我能夠重現此問題(使用 SQL Server 2012、PHP 7.1.12 和適用于 SQL Server 4.3.0+9904 的 PHP 驅動程序)并且您可以使用以下選項來解決此問題:
使用 刷新掛起的結果集
sqlsrv_next_result()
。在復雜的 T-SQL 語句中作為第一行執行
SET NOCOUNT ON
,以停止 SQL Server 將受影響的行數作為結果集返回。使用參數化語句使用
sqlsrv_prepare()\sqlsrv_execute()
桌子:
CREATE?TABLE?MyTable?( ????Column1?int, ????Column2?int, ????Column3?int)
一個復雜的語句(使用sqlsrv_query()
and?sqlsrv_next_result()
):
<?php?
// Connection info
$server = 'server\instance';
$database = 'database';
$username = 'username';
$password = 'password';
$cinfo = array(
? ? "Database" => $database,
? ? "UID" => $username,
? ? "PWD" => $password
);
// Statement with sqlsrv_query
$sql = "";
for ($i = 1; $i <= 1000; $i++) {
? ? $sql .= "INSERT INTO MyTable (Column1, Column2, Column3) VALUES (".$i.", 0, 0);";
}
$stmt = sqlsrv_query($con, $sql);
if ($stmt === false) {
? ? echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
? ? exit;
}
// Clean the buffer
while (sqlsrv_next_result($stmt) != null){};
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($con);
echo "OK";
?>
一個復雜的語句(使用sqlsrv_query()and SET NOCOUNT ON):
<?php?
// Connection info
$server = 'server\instance';
$database = 'database';
$username = 'username';
$password = 'password';
$cinfo = array(
? ? "Database" => $database,
? ? "UID" => $username,
? ? "PWD" => $password
);
// Connection
$con = sqlsrv_connect($server, $cinfo);
if ($con === false) {
? ? echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
? ? exit;
}
// Statement with sqlsrv_query
$sql = "SET NOCOUNT ON;";
for ($i = 1; $i <= 1000; $i++) {
? ? $sql .= "INSERT INTO MyTable (Column1, Column2, Column3) VALUES (".$i.", 0, 0);";
}
$stmt = sqlsrv_query($con, $sql);
if ($stmt === false) {
? ? echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
? ? exit;
}
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($con);
echo "OK";
?>
參數化語句(使用sqlsrv_prepare()and sqlsrv_execute()):
<?php?
// Connection info
$server = 'server\instance';
$database = 'database';
$username = 'username';
$password = 'password';
$cinfo = array(
? ? "Database" => $database,
? ? "UID" => $username,
? ? "PWD" => $password
);
// Connection
$con = sqlsrv_connect($server, $cinfo);
if ($con === false) {
? ? echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
? ? exit;
}
$sql = "INSERT INTO MyTable (Column1, Column2, Column3) VALUES (?, ?, ?);";
$value1 = 0;??
$value2 = 0;??
$value3 = 0;??
$params = array(&$value1, &$value2, &$value3);
$stmt = sqlsrv_prepare($con, $sql, $params);
if ($stmt === false ) {
? ? echo "Error (sqlsrv_prepare): ".print_r(sqlsrv_errors(), true);
? ? exit;
}
for ($i = 1; $i <= 1000; $i++) {
? ? $value1 = $i;??
? ? $value2 = 0;??
? ? $value3 = 0;??
? ? $result = sqlsrv_execute($stmt);
? ? if ($result === false) {
? ? ? ? echo "Error (sqlsrv_execute): ".print_r(sqlsrv_errors(), true);
? ? ? ? exit;
? ? }
}
// End
sqlsrv_free_stmt($stmt);
sqlsrv_close($con);
echo "OK";
?>
- 1 回答
- 0 關注
- 185 瀏覽
添加回答
舉報