PHP使用sqlsrv扩展调用SQL Server存储过程执行失败求助
问题原因及修复方案
- 输出参数未指定长度
sqlsrv扩展要求字符串类型的输出参数必须显式指定最大长度,否则无法正确接收存储过程的返回值,你的@PIdSobre(char(6))、@PStatusDescripcion(varchar(100))都属于字符串类型,未配置长度会导致返回值为NULL。 - 未遍历存储过程返回的结果集
如果存储过程执行过程中产生了任意结果集(哪怕是存储过程里临时SELECT调试的内容、影响行数返回),必须调用sqlsrv_next_result遍历完所有结果集后,输出参数才会被赋值,直接在sqlsrv_execute后读取变量会得到NULL。 - XML参数格式异常
你打印的XML内容为<MANIFIESTO><HEADER ID_SOBRE="",明显属于截断/格式错误状态,存储过程如果有XML格式校验逻辑会直接终止执行,不会给输出参数赋值。 - 可选优化:输入参数可显式指定SQL数据类型,避免隐式转换异常,比如
@PIdPuesto为int类型,可指定对应的SQLSRV_PHPTYPE_INT。
修正后代码示例
$fecha = DateTime::createFromFormat('d/m/Y H:i:s', $fecha); $fecha = $fecha->format('Y-m-d H:i:s'); $xml = $this->_encodingUtf8Latin1($xml); // 先校验XML格式合法性,避免传入非法内容 if (!simplexml_load_string($xml)) { die("XML格式错误"); } $idSobre = ''; // 初始化输出变量 $status = 0; $statusDescripcion = ''; $params = array( // 确认$puente变量已正确赋值为@PIdPuesto对应的传值 array(&$puente, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_INT), array(&$fecha, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_DATETIME), array(&$email, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_VARCHAR(50)), array(&$xml, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_VARCHAR('max')), // 输出参数增加长度配置 array(&$idSobre, SQLSRV_PARAM_OUT, null, SQLSRV_SQLTYPE_CHAR(6)), array(&$status, SQLSRV_PARAM_OUT, null, SQLSRV_SQLTYPE_INT), array(&$statusDescripcion, SQLSRV_PARAM_OUT, null, SQLSRV_SQLTYPE_VARCHAR(100)) ); $query = "EXEC USP_GrabaSobreTest @PIdPuesto = ?, @PFechaProgramada = ?, @PEmail = ?, @PXml = ?, @PIdSobre = ?, @PStatus = ?, @PStatusDescripcion = ?"; $stmt = sqlsrv_prepare($this->$_base, $query, $params); if($stmt === false) { echo "Error in executing statement 3.\n"; die( print_r( sqlsrv_errors(), true)); } else { $resultado = sqlsrv_execute($stmt); if ($resultado === false) { die( print_r( sqlsrv_errors(), true)); } // 遍历所有结果集,确保输出参数被赋值 while (sqlsrv_next_result($stmt)) { // 可处理中间返回的结果集,无结果则直接跳过 } // 此处再读取输出变量即可得到正确值 var_dump($idSobre, $status, $statusDescripcion); }
内容的提问来源于stack exchange,提问作者Santiago Amaro
相关产品推荐
相关产品推荐

