Я использую DB2 для IBM i (iSeries (AS / 400)), использую PHP 5.6.5, драйвер ibm_db2 на Zend Server 8.0.2.
Я столкнулся с примером, когда представление, которое содержит вложенные элементы, которые имеют псевдонимы, может возвращать или не возвращать несколько строк. Я не создал вид, я понимаю ошибку и могу ее исправить. Странно то, что в 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
который определен Вот. То, что я пытаюсь выяснить, это как обнаружить и изящно обработать E_WARNING, который генерируется db2_fetch_assoc()
, Причина в том, что, если я не обнаружу это, тогда процесс извлечения будет преимущественно завершен на первой поврежденной записи, но страница будет отображаться так, как будто все в порядке. Поэтому в будущем я хотел бы иметь на месте защитную систему, которая будет выявлять эти ситуации, а не осознавать, что месяцы спустя что-то не работает должным образом. К сожалению, второстепенное решение, которое я опубликовал в своем первом редактировании, не является жизнеспособным, поскольку все, о чем оно действительно сообщает, — это ошибка извлечения — ничего не касалось того, с чем связана эта ошибка. Это что-то, но не очень. В идеале я хотел бы представить, что есть способ получить коды состояний SQL или что-то еще (для моей ошибки это может быть любой из них: SQL0811, -811, 21000, которые определены в ссылке выше).
Кроме того, я не могу понять, почему ошибка SQL рассматривается только как E_WARNING в php. Мне это кажется странным, но я получаю то же поведение в iNavigator (т. Е. Он умирает, только когда вы попадаете в поврежденную строку), но не на зеленый экран (который выдает ошибку при выполнении запроса). Так что это должно быть как-то связано с драйверами БД и тем, как они справляются с этим.
Вы пытались использовать db2_stmt_errors в случае сбоя db2_prepare?
Тогда вы можете записать это в журнал
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
}
Других решений пока нет …