1

我正在使用 DB2 for IBM i(一个 iSeries (AS/400)),在 Zend Server 8.0.2 上使用 PHP 5.6.5 和 ibm_db2 驱动程序。

我遇到了一个实例,其中包含别名为名称的子选择的视图可能会或可能不会返回多行。我没有创建视图,我理解错误并且可以纠正它。奇怪的是,在 PHP 中,错误不会在 db2_exec() 上引发,而是在 db2_fetch_assoc() 上引发。我开始研究它,但找不到优雅地检测 db2_fetch_assoc() 生成的错误的方法。它在 Zend 错误日志中记录为“db2_fetch_assoc(): Fetch Failure”,E_WARNING 状态。

db2_stmt_error()并且db2_stmt_errormsg()只返回与 、 和 相关db2_exec()db2_execute()错误db2_prepare()。我什至尝试使用类似的东西:

try{
    //fetch record
}catch(Exception $exc){
    print_r($exc);
} 

并且它不会注册为异常。

我能想到的最好方法是发出初步查询以获取应返回的行数。然后使用这样的 for 循环:

for($rows = 0; $rows < $ttlRows; $rows++){
        if($row = db2_fetch_assoc($stmt, $rows)){
           //Do some stuff 
        }else{
            //Still never get to see information about the error or the afflicted row.
        }
    }

有谁知道优雅地检测、跟踪或处理此类实例的任何其他方法?

EDIT1: 我设法在这里找到值得一提的东西:PHP:如何优雅地管理错误? 这个答案描述了当警告发生时如何强制异常(这是我从 中得到的db2_fetch_assoc())。不利的一面是,如果没有发现任何警告,都会导致页面执行停止。

我正在考虑的想法是将我的整个页面包装在一个不执行任何操作的try-catch子句中catch(比如包含try{在页眉包含和}catch(Exception $exc){}页脚包含中)。这将允许页面执行,并且由于try-catch允许嵌套子句,我仍然可以像往常一样使用 try-catch。不过好像很脏。

EDIT2: 只是澄清一下,我并不是想弄清楚我遇到了什么错误或如何纠正它 - 我已经知道它是什么以及如何纠正它。但是为了记录,我得到的错误是这里SQL0811定义的。我想弄清楚的是如何检测并优雅地处理由db2_fetch_assoc(). 原因是因为如果我没有检测到它,那么提取过程将在第一个受影响的记录上抢先结束,但页面将呈现好像一切都很好。因此,对于未来,我希望有一个安全措施来检测这些情况,而不是在几个月后意识到某些事情无法正常工作。不幸的是,我在第一次编辑中发布的次要解决方案不是一个可行的解决方案,因为它真正报告的只是发生了一次提取失败 - 与失败的原因无关。这是一些东西,但不多。理想情况下,我想有一种方法可以获取 SQL 状态代码或其他东西(对于我的错误,可能是以下任何一个:SQL0811、-811、21000,它们在上面的链接中定义)。

此外,我无法弄清楚为什么 SQL 错误仅被视为 php.ini 中的 E_WARNING。对我来说似乎有点奇怪,但我在 iNavigator 中得到了相同的行为(即,它仅在您到达受影响的行时才会死亡)但不是绿屏(这会在查询执行时引发错误)。所以它必须与数据库驱动程序以及它们如何处理这个有关。

4

1 回答 1

0

Have you tried using db2_stmt_errors if db2_prepare fails ? Then you can write it out to a log

class ISeriesDB2 {

   protected $errorLog = '/tmp/error.log';
   protected $Conn;
   protected err;

   function __construct()
   {

       $this->Conn = $db2_connect(YOUR_HOST,YOUR_USER_YOUR_PASSWD);

   } 


  function query($SQL)

  {



		$this->sql = $SQL;
 
		 
		
		$stmt = db2_prepare($this->Conn, $this->sql);



        if ($stmt)
		{

			
			$result = db2_execute($stmt);
			

			while ($row = db2_fetch_assoc($stmt))
		   {
			 
			
				$resultSet[] = $row;
		   }


			db2_free_stmt($stmt);	
			return $resultSet;
		}
		else
		{
			
			$this->err = db2_stmt_errormsg();


			$this->writeError();

			return null;
		}
           
		
 



   }

   function writeError()
    {
       // write to the log

    }

于 2015-09-21T15:22:26.143 回答