我在Zend Server 8.0.2上使用PHP 5.6.5,ibm_db2驱动程序使用DB2 for IBM i(iSeries(AS / 400))。
我遇到了一个实例,其中包含名称别名的子选项的视图可能会也可能不会返回多行。我没有创建视图,我理解错误并且可以纠正它。奇怪的是,在PHP中,不会在db2_exec()上抛出错误,而是在db2_fetch_assoc()上抛出错误。我开始研究它,我找不到一种方法来优雅地检测db2_fetch_assoc()生成的错误。它在Zend错误日志中记录为" db2_fetch_assoc():获取失败",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: How to manage errors gracefully?
这个答案描述了如何在发生警告时强制执行异常(这是我从db2_fetch_assoc()
获得的)。缺点是如果没有捕获,任何警告都会导致页面执行停止。
我很有趣的想法是将我的整个页面包含在try-catch
条款中,其中catch
不执行任何操作(例如包括try{
在标题中包含和页脚中的}catch(Exception $exc){}
包括)。这将允许页面执行,并且由于允许嵌套的try-catch
子句,我仍然可以使用try-catch,就像我通常那样。虽然看起来很脏。
EDIT2:
只是为了澄清,我不是要弄清楚我得到的错误或如何纠正它 - 我已经知道它是什么以及如何纠正它。但是对于记录,我得到的错误是SQL0811
,其定义为here。我想弄清楚的是如何检测并优雅地处理由db2_fetch_assoc()
生成的E_WARNING。理由是因为如果我没有检测到它,那么获取过程将抢先结束第一个受折磨的记录,但页面将呈现为好像一切都很好。因此,对于未来,我希望有一个安全措施,可以检测到这些情况,而不是意识到几个月没有正常工作。不幸的是,我在第一次编辑中发布的次要解决方案并不是一个可行的解决方案,因为它真正报告的是提取失败 - 没有关于失败的原因。它是一些东西,但并不多。理想情况下,我认为有一种方法可以获取SQL状态代码或其他东西(对于我的错误,它将是以下任何一种:SQL0811,-811,21000,它们在上面的链接中定义)。
此外,我无法弄清楚为什么SQL错误在php中仅被视为E_WARNING。对我来说似乎有些奇怪,但是我在iNavigator中得到了相同的行为(即,只有当你到达一个受影响的行时才会死掉)但不是绿色屏幕(这会在查询执行时抛出错误)。所以它必须与数据库驱动程序及其处理方式有关。
答案 0 :(得分:0)
如果db2_prepare失败,您是否尝试过使用db2_stmt_errors? 然后你可以把它写到日志
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
}
&#13;