PHP读取文件调用SQL Server存储过程时出现Undefined array key错误
问题分析与修复方案
出现Undefined array key错误的核心原因是文件解析时数组元素数量不匹配,加上代码存在几处逻辑错误,以下是具体问题和修复后的代码:
主要问题点
- 数组解构不匹配:
list()期望$carray有10个元素,但文件中可能存在空行、格式错误的行,或者explode后的元素数量不足,导致变量无法对应数组键。 - 循环内过早关闭资源:
fclose($file)和sqlsrv_close($conn)放在while循环内部,第一次循环就关闭了文件和数据库连接,后续循环直接报错。 - 重复执行SQL语句:
sqlsrv_query已经完成语句的执行和预处理,不需要再调用sqlsrv_execute,这会导致重复执行的错误。 - 未处理换行符与空行:
fgets读取的内容包含换行符,且未跳过空行,导致解析出无效数组。
修复后的代码
// 先判断文件是否存在且可读 if (!file_exists($target_file) || !is_readable($target_file)) { die("文件不存在或无法读取"); } $file = fopen($target_file, "r"); // 跳过表头(如果文件有表头的话,没有可以注释掉) fgets($file); while(!feof($file)) { $content = fgets($file); // 去掉首尾空白字符(包括换行符),并跳过空行 $content = trim($content); if (empty($content)) { continue; } $carray = explode(",", $content); // 验证数组元素数量是否符合要求 if (count($carray) !== 10) { echo "无效行,元素数量不符:$content<br>"; continue; } list($INPUTXML, $UserName, $PosCode, $Password, $UserID, $CompanyID, $BranchID, $TerminalType, $UserType, $LOCADD) = $carray; $sql = "{CALL ITPAN_UPDATE (@INPUTXML= ?, @UserName= ?, @PosCode= ?, @Password= ?, @UserID= ?, @CompanyID= ?, @BranchID=?,@TerminalType= ?,@UserType=?,@LOCADD=?)}"; $params = array( array($INPUTXML, SQLSRV_PARAM_IN), array($UserName, SQLSRV_PARAM_IN), array($PosCode, SQLSRV_PARAM_IN), array($Password, SQLSRV_PARAM_IN), array($UserID, SQLSRV_PARAM_IN), array($CompanyID, SQLSRV_PARAM_IN), array($BranchID, SQLSRV_PARAM_IN), array($TerminalType, SQLSRV_PARAM_IN), array($UserType, SQLSRV_PARAM_IN), array($LOCADD, SQLSRV_PARAM_IN), ); $result = sqlsrv_query($conn, $sql, $params); if ($result === false) { echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true)."<br>"; continue; // 出错后继续处理下一行,不要直接exit } // 读取存储过程返回结果 if($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)){ echo print_r($row, true)."<br>"; } // 释放结果集资源 sqlsrv_free_stmt($result); } // 循环结束后再关闭文件和连接 fclose($file); sqlsrv_close($conn);
额外说明
- 添加了文件存在性检查,避免打开不存在的文件。
- 跳过空行和格式错误的行,避免因无效数据导致的数组键错误。
- 去掉了
sqlsrv_execute调用,sqlsrv_query已经完成执行。 - 循环结束后再关闭文件和数据库连接,保证所有行都能被处理。
- 若文件有表头行,保留
fgets($file)跳过表头;没有则注释该行。
内容的提问来源于stack exchange,提问作者Priya Tiwari
相关产品推荐
相关产品推荐

