PHP中odbc_execute配合odbc_fetch_row无返回值问题排查及解决
我在类中编写了如下预处理语句:
function reader($ser) { $pstmt=odbc_prepare($this->conn,'SELECT TOP 1 "name" FROM '.$this->table.' WHERE "surname" LIKE ? '); return odbc_execute($pstmt,array("$ser")); }
该函数通过POST获取参数$ser,示例值为:
$ser=' \'3221252\'';
调用方式为:
$serTab=$product->reader($ser);
但使用以下代码无法获取返回值(改用odbc_exec可正常工作):
while(odbc_fetch_row($serTab)) { for($i=1;$i<=odbc_num_fields($serTab);$i++) { echo odbc_result($serTab,$i); } }
请问为何使用odbc_execute时无返回值?如何修复?是否有这些函数的替代方案?
另外,因出现错误「Conversion of parameter/column (5) from data type NVARCHAR to ASCII failed」,无法使用PDO;且我无数据库修改权限,DBMS为SAP Hana。
为什么odbc_execute无返回值?
odbc_execute()的返回值是布尔值(成功返回true,失败返回false),而非结果集资源。你将它的返回值赋值给$serTab,后续调用odbc_fetch_row()时自然无法处理——因为这个函数需要的是odbc_prepare()返回的预处理语句资源,或是odbc_exec()返回的结果集资源,而非布尔值。
而odbc_exec()会直接执行SQL并返回结果集资源,所以能正常遍历。
修复方法
修改reader()函数,返回预处理语句资源$pstmt,而非odbc_execute()的返回值。调用时先执行odbc_execute(),再用返回的资源处理结果集:
修改后的reader()函数
function reader($ser) { $pstmt=odbc_prepare($this->conn,'SELECT TOP 1 "name" FROM '.$this->table.' WHERE "surname" LIKE ? '); odbc_execute($pstmt,array($ser)); return $pstmt; }
调用代码保持不变
$serTab=$product->reader($ser); while(odbc_fetch_row($serTab)) { for($i=1;$i<=odbc_num_fields($serTab);$i++) { echo odbc_result($serTab,$i); } }
额外注意:你的示例$ser值包含多余单引号,预处理语句会自动处理参数转义,建议把$ser=' \'3221252\'';改成$ser='3221252';;如果需要模糊匹配,应在参数里添加通配符(如$ser='%3221252%';),而非手动拼接单引号。
替代方案
由于PDO因NVARCHAR转ASCII失败无法使用,可考虑以下方案:
- 使用
odbc_exec()结合参数转义:用odbc_escape_string()转义参数后拼接SQL,但这种方式存在SQL注入风险,仅适用于参数完全可控的场景。 - 调整ODBC驱动字符集配置:在ODBC数据源设置中,尝试将字符集改为UTF-8或对应NVARCHAR的编码(如UTF-16),看是否能解决PDO的转换错误,从而切换到更现代的PDO操作方式。
内容的提问来源于stack exchange,提问作者wittream

