ODBC_CONNECT游标类型与使用freeTDS和unixODBC的PHP中的SQLGetData冲突

问题描述:

我有一个运行在我的Gentoo Linux上的PHP项目,它使用FreeTDS & UnixODBC连接到Windows服务器上的MSSQL数据库。我有这个项目使用这个确切的代码多年,但最近我不得不更新PHP时,Gentoo不再有一个5.3版本的ebuild portage和其他系统更新需要发生。ODBC_CONNECT游标类型与使用freeTDS和unixODBC的PHP中的SQLGetData冲突

正在使用的各种软件的最新版本是:
PHP版本为5.6.17
freetds的是0.91版本
的unixODBC是2.3.2版本-R1

但现在一些完全相同的查询可以完美地返回这个错误。

PHP Warning: odbc_fetch_object(): SQL error: [unixODBC][Driver Manager]SQLGetData is not allowed on a forward only (non-buffered) cursor, SQL state SL008 in SQLGetData in /home/XXXXX/XXXX.php on line Y

并不是所有的查询返回此错误,只有一些,但相同的查询一致地返回相同的错误。

一个简单的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它返回错误:

Warning: odbc_fetch_object(): No tuples available at this result index in /home/XXXXX/XXXX.php on line Y []

随着相同的结果为SQL_CUR_USE_DRIVER,或者如果它是空白。

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

任何帮助或方向在这个问题将不胜感激。

+0

我知道这已经过了一年了,但我看到的是一个非常类似的配置,并且发现只有当选择了文本数据类型,并且数据仍然被选中,但是有一个php WARNING for在Text数据类型列上调用每个'odbc_result'。你有没有找到一个更持久的警告解决方案? –

+0

我其实从来没有专门做过。我有点忘记了这个问题。我觉得我必须刚刚切换到PHP版本!但我欢迎任何其他人弄清楚这是怎么回事,让我们其他人知道! – dynamphorous

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

但是,其中一个ODBC或TDS库中的一些故障导致警告,以阻止SQL的执行。这不是一个伟大的解决方案,但包括设置ANSI_WARNINGS关在查询开始时关闭警告,现在代码执行完全像以前一样。

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

是我现在查询字符串的样子。不理想,但它的工作原理。

我发现的第一个主要提示是它只发生在我们用文本列和其他列做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有一些大小限制。