1 回答

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超4個(gè)贊
說(shuō)明:
提供的解決方案的一部分是以下解釋?zhuān)?/p>
似乎在執(zhí)行大量 SQL 語(yǔ)句時(shí),Microsoft SQL Server 可能會(huì)在執(zhí)行批處理中的所有語(yǔ)句之前停止處理該批處理。處理批處理的結(jié)果時(shí),SQL Server 使用批處理創(chuàng)建的結(jié)果集填充連接的輸出緩沖區(qū)。這些結(jié)果集必須由客戶(hù)端應(yīng)用程序處理。如果您正在執(zhí)行具有多個(gè)結(jié)果集的大型批處理,SQL Server 會(huì)填充該輸出緩沖區(qū),直到它達(dá)到內(nèi)部限制并且無(wú)法繼續(xù)處理更多結(jié)果集。那時(shí),控制權(quán)返回給客戶(hù)端。此行為是設(shè)計(jì)使然??蛻?hù)端應(yīng)用程序應(yīng)刷新所有待處理的結(jié)果集。一旦所有掛起的結(jié)果集都被客戶(hù)端使用,SQL Server 就會(huì)完成批處理的執(zhí)行。客戶(hù)端應(yīng)用程序可以調(diào)用 sqlsrv_next_result() 直到它返回 NULL。
因此,我認(rèn)為 SQL 語(yǔ)句的長(zhǎng)度沒(méi)有限制,只有 PHP 字符串變量($InsertSQL
在您的情況下)的大小被限制為允許的最大 PHP 內(nèi)存限制。這種意外行為的實(shí)際原因是,對(duì)于SET NOCOUNT OFF
(默認(rèn)情況下)和大量的單個(gè)INSERT
語(yǔ)句,SQL Server 將受影響的行數(shù)作為結(jié)果集返回(例如(1 row affected)
)。
解決方案:
我能夠重現(xiàn)此問(wèn)題(使用 SQL Server 2012、PHP 7.1.12 和適用于 SQL Server 4.3.0+9904 的 PHP 驅(qū)動(dòng)程序)并且您可以使用以下選項(xiàng)來(lái)解決此問(wèn)題:
使用 刷新掛起的結(jié)果集
sqlsrv_next_result()
。在復(fù)雜的 T-SQL 語(yǔ)句中作為第一行執(zhí)行
SET NOCOUNT ON
,以停止 SQL Server 將受影響的行數(shù)作為結(jié)果集返回。使用參數(shù)化語(yǔ)句使用
sqlsrv_prepare()\sqlsrv_execute()
桌子:
CREATE?TABLE?MyTable?( ????Column1?int, ????Column2?int, ????Column3?int)
一個(gè)復(fù)雜的語(yǔ)句(使用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";
?>
一個(gè)復(fù)雜的語(yǔ)句(使用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";
?>
參數(shù)化語(yǔ)句(使用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 關(guān)注
- 195 瀏覽
添加回答
舉報(bào)