【问题标题】:ODBC_CONNECT cursor type conflict with SQLGetData in PHP with freeTDS and unixODBCODBC_CONNECT 游标类型与带有 freeTDS 和 unixODBC 的 PHP 中的 SQLGetData 冲突
【发布时间】:2016-02-18 16:08:43
【问题描述】:

我有一个 PHP 项目在我的 Gentoo Linux 上运行,它使用 FreeTDS 和 UnixODBC 连接到 Windows 服务器上的 MSSQL 数据库。我已经让这个项目使用这个确切的代码多年了,但最近我不得不更新 PHP,因为 Gentoo 不再有 portage 中的 5.3 版 ebuild 并且需要进行其他系统更新。

当前使用的各种软件的版本是:
PHP 版本为 5.6.17
FreeTDS 是 0.91 版
UnixODBC 是版本 2.3.2-r1

但现在一些以前可以完美运行的查询却返回了这个错误。

PHP 警告:odbc_fetch_object():SQL 错误:[unixODBC][驱动程序 Manager]SQLGetData 不允许仅转发(非缓冲) 游标,SQLGetData中SQL状态SL008在/home/XXXX/XXXX.php上线 是的

并非所有查询都返回此错误,只有一些,但相同的查询始终返回相同的错误。

会返回此错误的简单 PHP 程序如下:

$con = odbc_connect(DBNAME,UNAME,PW,SQL_CUR_USE_ODBC)
$query = "SELECT * FROM SomeTable"
$Output = odbc_exec($con,$query);
$return_array = array();
while($row = odbc_fetch_object($Output)){
#
        foreach($row as &$value){
                $value = mb_convert_encoding($value, "UTF-8", "Windows-1252");
        }
        unset($value);
        $return_array[] = $row;
}
echo json_encode($return_array,JSON_UNESCAPED_UNICODE);
odbc_close($con);
?>

现在这肯定与使用 SQL_CUR_USE_ODBC 时提供给 odbc_connect 的第四个参数有关,错误正如我上面所说的。当它更改为 SQL_CUR_USE_IF_NEEDED 时,它会返回错误:

警告:odbc_fetch_object():在 /home/XXXXX/XXXX.php 第 Y 行 [] 上的此结果索引处没有可用的元组

SQL_CUR_USE_DRIVER 的结果相同,或者如果它留空。

同样,两天前,这是所有查询中的所有功能代码。所以从 PHP 5.3 到 php > 5.3 的任何版本都发生了变化。从 5.4 到 7.0 的每个版本的 PHP 都已尝试过(portage 中有一个 PHP 7 ebuild)并且都产生了相同的错误。

在此问题上的任何帮助或指导将不胜感激。

【问题讨论】:

  • 我知道这已经有一年了,但我看到了同样的配置,配置非常相似,并注意到只有在选择了文本数据类型时,数据仍然被选中,但在那里是对 Text 数据类型列上的每个 odbc_result 调用的 php 警告。你有没有为警告找到更持久的解决方案?
  • 其实我从来没有具体做过。老实说,我有点忘记了这个问题。我觉得我一定是刚刚切换了 PHP 的版本!但我欢迎其他任何弄清楚这是怎么回事的人让我们其他人知道!

标签: php sql-server odbc freetds unixodbc


【解决方案1】:

我发现的第一个主要提示是,只有在我们对文本列和其他列执行 SELECT 时才会发生这种情况。单独在文本列上使用 SELECT 不会引发错误。并且选择除文本列之外的所有其他列都不会引发错误。我们刚刚从 SQL Server 2000 迁移到 2008,所以我非常愿意尝试 VARCHAR(MAX) 来支持我们在 2000 年必须使用的文本列。

ALTER TABLE tbl_name ALTER COLUMN col_name VARCHAR(MAX) [NOT] NULL 为我们修复了所有这些错误消息。即使返回了几 KB 的文本,它也能很好地传输 VARCHAR(MAX)。旧的 Text 实现将列大小保留为 2GB,所以我假设 FreeTSD 0.91 有一些大小限制。

【讨论】:

    【解决方案2】:

    经过大量测试,解决此问题的方法是注意这些只是警告,而不是错误。它们应该被抛出,但随后也会执行 SQL。

    但是,这些 ODBC 或 TDS 库之一中的一些故障导致警告阻止 SQL 的执行。这不是一个很好的解决方案,但在查询开始时包含 SET ANSI_WARNINGS OFF 会关闭警告,现在代码的执行方式与之前完全一样。

    $query = 'SET ANSI_WARNINGS OFF
              SELECT * FROM SomeTable';
    

    是我的查询字符串现在的样子。不理想,但可以。

    【讨论】:

      【解决方案3】:

      我遇到了这个确切的问题。在我的查询解决问题之前添加“SET ANSI_WARNINGS OFF”。谢谢。

      Freetds 版本:0.91.112 PHP 版本 5.3.29

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-09
        • 2011-02-24
        • 2019-12-20
        • 2013-05-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多