2010-03-31 6 views
47

Я пытаюсь разгадать MySqli, и я смущен сообщением об ошибках. Я использую возвращаемое значение MySQLi «подготовить» заявление для обнаружения ошибок при выполнении SQL, например:MySQLi подготовил отчеты об ошибках

$stmt_test = $mysqliDatabaseConnection->stmt_init(); 
if($stmt_test->prepare("INSERT INTO testtable VALUES (23,44,56)")) 
{ 
$stmt_test->execute(); 
$stmt_test->close(); 
} 
else echo("Statement failed: ". $stmt_test->error . "<br>"); 

Но это возвращаемое значения подготовить заявление только обнаружение, если есть ошибка в предварительная инструкция SQL и не обнаружение ошибок выполнения? Если это так я должен поэтому изменить выполнить линию ошибок флаг, а так:

if($stmt_test->execute()) $errorflag=true; 

А потом на всякий случай я должен также сделать следующее после того, как оператор выполнил:

if($stmt_test->errno) {$errorflag=true;} 

. ..Or был ли я в порядке, чтобы начать с, и возвращаемое значение в инструкции MySQLi prepare фиксирует все ошибки, связанные с полным выполнением заданного им запроса?

Благодаря C

+0

Почему вы используете подготовить/Execute() вместо запроса() в первую очередь когда в строке запроса нет переменной? Или это просто упрощённый пример? – VolkerK

+0

Да, извините. Было упрощено показать, как я с трудом понимал, где получить окончательную отчетность об ошибках из подготовленного материала. – Columbo

ответ

98

Я написал это дважды в течение последних двух дней (так что для меня это дубликат, даже если вопросы начали немного по-другому).

Каждый способ mysqli может завершиться неудачей. Вы должны проверить каждое возвращаемое значение. Если кто-то терпит неудачу, подумайте о том, имеет ли смысл продолжать объект, который не находится в состоянии, которое вы ожидаете от него. (Потенциально не в «безопасном» состоянии, но я думаю, что это не проблема.)

Так как только сообщение об ошибке для последней операции хранится для каждого соединения/оператора, вы можете потерять информацию о , что вызвало ошибку если вы продолжаете, когда что-то пошло не так. Возможно, вы захотите использовать эту информацию, чтобы позволить сценарию решить, следует ли повторять попытку (только временную проблему), что-то изменить или полностью выпустить (и сообщить об ошибке). И это делает отладку намного проще.

$stmt = $mysqli->prepare("INSERT INTO testtable VALUES (?,?,?)"); 
// prepare() can fail because of syntax errors, missing privileges, .... 
if (false===$stmt) { 
    // and since all the following operations need a valid/ready statement object 
    // it doesn't make sense to go on 
    // you might want to use a more sophisticated mechanism than die() 
    // but's it's only an example 
    die('prepare() failed: ' . htmlspecialchars($mysqli->error)); 
} 

$rc = $stmt->bind_param('iii', $x, $y, $z); 
// bind_param() can fail because the number of parameter doesn't match the placeholders in the statement 
// or there's a type conflict(?), or .... 
if (false===$rc) { 
    // again execute() is useless if you can't bind the parameters. Bail out somehow. 
    die('bind_param() failed: ' . htmlspecialchars($stmt->error)); 
} 

$rc = $stmt->execute(); 
// execute() can fail for various reasons. And may it be as stupid as someone tripping over the network cable 
// 2006 "server gone away" is always an option 
if (false===$rc) { 
    die('execute() failed: ' . htmlspecialchars($stmt->error)); 
} 

$stmt->close(); 

редактировать: только несколько замечаний спустя шесть лет ....
MySQLi расширение вполне способен операция, которые приводят к возникновению (Mysqli) код ошибки, отличной от 0 через исключение отчетности см mysqli_driver::$report_mode.
die() действительно очень груб, и я бы не использовал его даже для таких примеров, как этот.
Так что, пожалуйста, уберите только тот факт, что каждый (mysql) операция может не по ряду причин; даже , если точно такая же вещь прошла тысячу раз раньше ....

+2

Спасибо. Я только что проверил и посмотрю, что вы говорите. Если я создаю quesry, который вставляет дублирующее значение первичного ключа в таблицу, тогда проверка только подготовки не покажет, что вставка не удалась. С другой стороны, если я не проверю готовность, выполнение никогда не произойдет (я получу несколько предупреждений о включении предупреждений IF). Поэтому я вижу, что ты прав. Благодарю. – Columbo

+0

О да, ограничения - прекрасный пример. Если возможно, я задал бы вопрос _ еще один +1 для этого ;-) – VolkerK

+0

Я не могу выдвинуть этот ответ достаточно –

4

Не уверен, если это отвечает на ваш вопрос или нет. Извините, если нет

Чтобы получить сообщение об ошибке из базы данных mysql о вашем запросе, вам необходимо использовать объект подключения в качестве фокуса.

так:

echo $mysqliDatabaseConnection->error 

бы повторить ошибку, посылаемые MySQL о запросе.

Надежда, что помогает

+0

Спасибо. Поэтому, если я запрашиваю ошибку для фактического объекта соединения, то он даст мне последнюю ошибку для этого соединения. Поскольку выполнение будет выполнено только в том случае, если все предыдущие шаги преуспели, тогда это скажет мне, все ли прошло хорошо. Я полагаю, что тот же результат можно было бы получить, просто проверив ошибку для команды выполнения, как это было указано ниже в Col Shrapnel. Правильно ли я считаю, что проверка флага успеха/сбоя в подготовительном заявлении не служит реальной цели? – Columbo

+0

Я думаю, что вы, возможно, уже имеете свой ответ выше, но все равно ответят из вежливости. Essential Prepare может выйти из строя, как сказал VolekrK, но он не вернет ошибку mysql. Таким образом, вам нужно выяснить, почему подготовка не удалось, получив ошибку подключения mysql, которая даст вам указание о том, что запрос в вашем отчете о подготовке не прошел. Я не уверен в ошибке выполнения команды. – andyface

11

Полнота

Вы должны проверить как $mysqli и $statement. Если они ложны, вам необходимо вывести $mysqli->error или $statement->error соответственно.

Эффективность

Для простых сценариев, которые могут кончить, я использую простые остроты, которые вызывают ошибку PHP с сообщением. Для более сложного приложения вместо этого следует активировать систему предупреждения об ошибках, например, путем исключения исключения.

Использование Пример 1: Простой скрипт

# This is in a simple command line script 
$mysqli = new mysqli('localhost', 'buzUser', 'buzPassword'); 
$q = "UPDATE foo SET bar=1"; 
($statement = $mysqli->prepare($q)) or trigger_error($mysqli->error, E_USER_ERROR); 
$statement->execute() or trigger_error($statement->error, E_USER_ERROR); 

Пример использования 2: Применение

# This is part of an application 
class FuzDatabaseException extends Exception { 
} 

class Foo { 
    public $mysqli; 
    public function __construct(mysqli $mysqli) { 
    $this->mysqli = $mysqli; 
    } 
    public function updateBar() { 
    $q = "UPDATE foo SET bar=1"; 
    $statement = $this->mysqli->prepare($q); 
    if (!$statement) { 
     throw new FuzDatabaseException($mysqli->error); 
    } 

    if (!$statement->execute()) { 
     throw new FuzDatabaseException($statement->error); 
    } 
    } 
} 

$foo = new Foo(new mysqli('localhost','buzUser','buzPassword')); 
try { 
    $foo->updateBar(); 
} catch (FuzDatabaseException $e) 
    $msg = $e->getMessage(); 
    // Now send warning emails, write log 
} 
+0

1. die() не следует использовать когда-либо. 2. mysqli может самостоятельно генерировать исключения, см. Mysqli_report() 2. Написание кода для «отправки предупреждающих писем, записи журнала» после * каждого * управляемых базой данных функций ужасно избыточно. –

+0

@Your Common Sense Bullshit. Если вы используете простые скрипты, которые вы выполняете, умереть - это нормально. – cmc

+0

Во всяком случае, вы никогда не должны использовать API mysqli как есть, но только завернуты в некоторую библиотеку более высокого уровня. –

Смежные вопросы