Mysql query select exception

Обработка ошибок MySQL в хранимых процедурах

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

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

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

Объявление обработчика

Чтобы объявить обработчик мы используем оператор DECLARE HANDLER :

Если значение условия совпадает со значением condition_value , MySQL выполнит оператор statement и продолжит или завершит текущий блок кода, исходя из значения action .

action может принимать следующие значения:

  • CONTINUE : исполнение блокированного кода (BEGIN … END) продолжается;
  • EXIT : выполнение блокированного кода, в котором был объявлен обработчик, завершается.

condition_value задает конкретное условие или класс условия, которые активируют обработчик.

condition_value может принимать одно из следующих значений:

  • код ошибки MySQL ;
  • стандартное значение SQLSTATE . Или это может быть условие SQLWARNING , NOTFOUND или SQLEXCEPTION , которое является сокращением для класса значений SQLSTATE . Условие NOTFOUND используется для курсора или оператора SELECT INTO variable_list ;
  • название условия, связанного либо с кодом ошибки MySQL , либо со значением SQLSTATE .

В качестве statement может использоваться простой оператор или составной оператор, вшитый с помощью ключевых слов BEGIN и END .

Примеры обработки ошибок MySQL

Давайте рассмотрим несколько примеров объявления обработчиков.

Обработчик, приведенный ниже, означает: когда происходит ошибка, устанавливается значение переменной has_error 1 и выполнение продолжается:

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

Если вы объявляете его внутри блока BEGIN END хранимой процедуры, он немедленно завершает хранимую процедуру:

Если строк для вывода больше нет, для вариантов cursor или оператора SELECT INTO , значение переменной no_row_found устанавливается равным 1 и продолжается исполнение:

При возникновении ошибки дублирования ключа, выдается ошибка MySQL 1062 . Следующий обработчик выдает сообщение об ошибке и продолжает выполнение:

Пример обработчика MySQL в хранимых процедурах

Во-первых , для демонстрации мы создаем новую таблицу с именем article_tags :

В таблице article_tags хранятся связи между статьями и тегами. К каждой статье может относиться несколько тегов и наоборот.

Для простоты, мы не будем создавать таблицы articles и tags , а также внешние ключи в таблице article_tags .

Во-вторых , мы создаем хранимую процедуру, которая вставляет пару идентификаторов статьи и тега в таблицу article_tags :

В-третьих , для статьи 1 мы добавляем идентификаторы тега 1, 2 и 3, с помощью вызова хранимой процедуры insert_article_tags :

Четвертое . Давайте попробуем вставить дубликат ключа, чтобы увидеть, действительно ли вызывается обработчик:

Мы получили сообщение об ошибке. Однако, поскольку мы объявили тип обработчика CONTINUE , хранимая процедура продолжает исполняться.

В результате, мы все равно получили список тегов для статьи:

Если мы в объявлении обработчика изменим команду CONTINUE на EXIT , мы получим только сообщение об ошибке:

Теперь, мы можем попробовать добавить дубликат ключа, чтобы увидеть результат:

Приоритет обработчиков MySQL

В случае если у вас есть несколько обработчиков, которые имеют право обрабатывать ошибку, MySQL для обработки ошибки будет вызывать наиболее подходящий обработчик.

Ошибка всегда обозначается одним из кодов ошибки MySQL , так что MySQL в этом плане имеет возможность четко их идентифицировать.

Обозначения SQLSTATE для многих кодов ошибок MySQL менее специфичны. SQLEXCPETION или SQLWARNING представляют собой сокращения класса значений SQLSTATES , поэтому они имеют общий характер.

На основании правил приоритета обработчиков обработчик кода ошибки MySQL , обработчик SQLSTATE и обработчик SQLEXCEPTION имеют приоритеты один, два и три соответственно.

Предположим, что в хранимой процедуре insert_article_tags_3 мы объявляем три обработчика:

Теперь мы пробуем добавить в таблицу article_tags дубликат ключа через вызов хранимой процедуры:

Читайте также:  Error code 2 для driver san francisco

Как видите, вызывается обработчик кода ошибки MySQL :

Использование проименованных условий ошибки

Начинаем с объявления обработчика ошибки:

Что означает код 1051 ? Представьте, что у вас есть большая хранимая процедура, по всему коду которой разбросаны некорректные значения. Настоящий кошмар для разработчиков обслуживания.

К счастью, MySQL предоставляет нам оператор DECLARE CONDITION , который объявляет проименованное условие ошибки, связанное с условием.

Синтаксис оператора DECLARE CONDITION выглядит следующим образом:

condition_value может представлять собой код ошибки MySQL , например 1015 , или значение SQLSTATE . condition_value представляется с помощью condition_name .

После объявления вы можете обращаться к condition_name вместо condition_value .

Таким образом, мы можем переписать код, приведенный выше, следующим образом:

Этот код, очевидно, более удобен для чтения, нежели предыдущий. Отметим, что объявление условия должно размещаться перед объявлением обработчика или объявлением курсора.

Сергей Бензенко автор-переводчик статьи « MySQL Error Handling in Stored Procedures »

Источник

mysqli::$error

(PHP 5, PHP 7, PHP 8)

mysqli::$error — mysqli_error — Returns a string description of the last error

Description

Returns the last error message for the most recent MySQLi function call that can succeed or fail.

Parameters

Procedural style only: A mysqli object returned by mysqli_connect() or mysqli_init()

Return Values

A string that describes the error. An empty string if no error occurred.

Examples

Example #1 $mysqli->error example

= new mysqli ( «localhost» , «my_user» , «my_password» , «world» );

/* check connection */
if ( $mysqli -> connect_errno ) <
printf ( «Connect failed: %s\n» , $mysqli -> connect_error );
exit();
>

if (! $mysqli -> query ( «SET a=1» )) <
printf ( «Error message: %s\n» , $mysqli -> error );
>

/* close connection */
$mysqli -> close ();
?>

= mysqli_connect ( «localhost» , «my_user» , «my_password» , «world» );

/* check connection */
if ( mysqli_connect_errno ()) <
printf ( «Connect failed: %s\n» , mysqli_connect_error ());
exit();
>

if (! mysqli_query ( $link , «SET a=1» )) <
printf ( «Error message: %s\n» , mysqli_error ( $link ));
>

/* close connection */
mysqli_close ( $link );
?>

The above examples will output:

See Also

  • mysqli_connect_errno() — Returns the error code from last connect call
  • mysqli_connect_error() — Returns a description of the last connection error
  • mysqli_errno() — Returns the error code for the most recent function call
  • mysqli_sqlstate() — Returns the SQLSTATE error from previous MySQL operation

User Contributed Notes 7 notes

The mysqli_sql_exception class is not available to PHP 5.05

I used this code to catch errors
= «SELECT XXname FROM customer_table » ;
$res = $mysqli -> query ( $query );

if (! $res ) <
printf ( «Errormessage: %s\n» , $mysqli -> error );
>

?>
The problem with this is that valid values for $res are: a mysqli_result object , true or false
This doesn’t tell us that there has been an error with the sql used.
If you pass an update statement, false is a valid result if the update fails.

So, a better way is:
= «SELECT XXname FROM customer_table » ;
$res = $mysqli -> query ( $query );

if (! $mysqli -> error ) <
printf ( «Errormessage: %s\n» , $mysqli -> error );
>

?>

This would output something like:
Unexpected PHP error [mysqli::query() [function.query]: (42S22/1054): Unknown column ‘XXname’ in ‘field list’] severity [E_WARNING] in [G:\database.php] line [249]

Very frustrating as I wanted to also catch the sql error and print out the stack trace.

A better way is:

( MYSQLI_REPORT_OFF ); //Turn off irritating default messages

$mysqli = new mysqli ( «localhost» , «my_user» , «my_password» , «world» );

$query = «SELECT XXname FROM customer_table » ;
$res = $mysqli -> query ( $query );

if ( $mysqli -> error ) <
try <
throw new Exception ( «MySQL error $mysqli -> error
Query:
$query » , $msqli -> errno );
> catch( Exception $e ) <
echo «Error No: » . $e -> getCode (). » — » . $e -> getMessage () . «
» ;
echo nl2br ( $e -> getTraceAsString ());
>
>

//Do stuff with the result
?>
Prints out something like:
Error No: 1054
Unknown column ‘XXname’ in ‘field list’
Query:
SELECT XXname FROM customer_table

#0 G:\\database.php(251): database->dbError(‘Unknown column . ‘, 1054, ‘getQuery()’, ‘SELECT XXname F. ‘)
#1 G:\data\WorkSites\1framework5\tests\dbtest.php(29): database->getString(‘SELECT XXname F. ‘)
#2 c:\PHP\includes\simpletest\runner.php(58): testOfDB->testGetVal()
#3 c:\PHP\includes\simpletest\runner.php(96): SimpleInvoker->invoke(‘testGetVal’)
#4 c:\PHP\includes\simpletest\runner.php(125): SimpleInvokerDecorator->invoke(‘testGetVal’)
#5 c:\PHP\includes\simpletest\runner.php(183): SimpleErrorTrappingInvoker->invoke(‘testGetVal’)
#6 c:\PHP\includes\simpletest\simple_test.php(90): SimpleRunner->run()
#7 c:\PHP\includes\simpletest\simple_test.php(498): SimpleTestCase->run(Object(HtmlReporter))
#8 c:\PHP\includes\simpletest\simple_test.php(500): GroupTest->run(Object(HtmlReporter))
#9 G:\all_tests.php(16): GroupTest->run(Object(HtmlReporter))

Читайте также:  An error has occurred in the program during initialization 0x80073b01

This will actually print out the error, a stack trace and the offending sql statement. Much more helpful when the sql statement is generated somewhere else in the code.

The decription «mysqli_error — Returns a string description of the LAST error» is not exactly that what you get from mysqli_error. You get the error description from the last mysqli-function, not from the last mysql-error.

If you have the following situation

if (!$mysqli->query(«SET a=1»)) <
$mysqli->query(«ROLLBACK;»)
printf(«Errormessage: %s\n», $mysqli->error);
>

you don’t get an error-message, if the ROLLBACK-Query didn’t failed, too. In order to get the right error-message you have to write:

if (!$mysqli->query(«SET a=1»)) <
printf(«Errormessage: %s\n», $mysqli->error);
$mysqli->query(«ROLLBACK;»)
>

I had to set mysqli_report(MYSQLI_REPORT_ALL) at the begin of my script to be able to catch mysqli errors within the catch block of my php code.

Initially, I used the below code to throw and subsequent catch mysqli exceptions

try <
$mysqli = new mysqli ( ‘localhost’ , ‘root’ , ‘pwd’ , ‘db’ );
if ( $mysqli -> connect_errno )
throw new Exception ( $mysqli -> connect_error );

> catch ( Exception $e ) <
echo $e -> getMessage ();
>

I realized the exception was being thrown before the actual throw statement and hence the catch block was not being called .

My current code looks like
mysqli_report ( MYSQLI_REPORT_ALL ) ;
try <
$mysqli = new mysqli ( ‘localhost’ , ‘root’ , ‘pwd’ , ‘db’ );
/* I don’t need to throw the exception, it’s being thrown automatically */

> catch ( Exception $e ) <
echo $e -> getMessage ();
>

This works fine and I ‘m able to trap all mysqli errors

// The idea is the add formated errors information for developers to easier bugs detection.

$myfile = fopen ( «database_log.log» , «r» );
$db = new mysqli ( «localhost» , «root» , «root» , «data» );
if(! $db -> query ( «SELECT» )) <
$timestamp = new DateTime ();
$data_err = » <
\»title\»: \» Select statement error \»,
\»date_time\»: » . $timestamp -> getTimestamp (). «,
\»error\»:\» » . $db -> error . » \»
> » ; // Do more information
fwrite ( $myfile , $data_err ); // writing data
>
// In separate file do file read and format it for good visual.

$db -> close ();
fclose ( $myfile );
?>

Please note that the string returned may contain data initially provided by the user, possibly making your code vulnerable to XSS.

So even if you escape everything in your SQL query using mysqli_real_escape_string(), make sure that if you plan to display the string returned by mysqli_error() you run that string through htmlspecialchars().

As far as I can tell the two escape functions don’t escape the same characters, which is why you need both (the first for SQL and the second for HTML/JS).

Hi, you can also use the new mysqli_sql_exception to catch sql errors.
Example:
//set up $mysqli_instance here..
$Select = «SELECT xyz FROM mytable » ;
try <
$res = $mysqli_instance -> query ( $Select );
>catch ( mysqli_sql_exception $e ) <
print «Error Code
» . $e -> getCode ();
print «Error Message
» . $e -> getMessage ();
print «Strack Trace
» . nl2br ( $e -> getTraceAsString ());
>

Источник

MySQL Error Handling

This article is half-done without your Comment! *** Please share your thoughts via Comment ***

In this post, I am sharing the full demonstration on how to manage error/exception handling in the Stored Procedure of MySQL.

Whenever an exception is occurring in a stored procedure, it is very important to handle it by showing proper error messages.

If you do not handle the exception, there would be a chance to fail application with the certain exception in a stored procedure.

If you get an error in stored procedure, instead of an exit, you should continue without any error message. That means you can show any default or custom error code or message to the application/user.

MySQL provides Handler to handle the exception in the stored procedure.

Читайте также:  What is trap exception

Below is a full demonstration of a handler with examples:

How to declare handler in store procedure:

Three type of Handler_Action:

Type of Condition Value:

  • mysql_error_code
  • sqlstate_value
  • SQLWarning
  • SQLException
  • NotFound

How to write handler in stored procedure?

The Above are four different handler examples. Now, I am going to insert a duplicate value into EmpID column.

In the above SP, I defined a CONTINUE handler with my custom exception message.

Now, call the above SP two times with same EmpID.

The first time, it will execute successfully, but the second time it will throw a custom error message.

As we defined CONTINUE handler, so it will just show an error message and CONTINUE to next part of the SELECT statement.

Above are the two different calls with same EmpID value. The first call executes without any error message and the second call execute with an error message.

The resule of Second Call:

As we defined CONTINUE, so you can find two results in above image. One is our custom error message and second is the result of the defined SELECT statement.
The execution didn’t stop by error, and it continued for another part.

Now, check the EXIT handler:

Please modify your handler and replace CONTINUE by EXIT:

Call with the same parameter:

The Result is an only error message, and you cannot find two results as we defined EXIT to exit the code when an error occurred.

The best practice is to create a output parameter and store 1 if any error occurred.

Application code has to check this output parameter is NULL or 1.

Below is a stored procedure for this:

Now call the above SP and select output parameter:

Now Results are:

Above is a simple demonstration of Error Handling in MySQL. You can also use SQLSTATE which shows default error messages of MySQL.

hi Avnesh i am struggling with DEFINER in stored procedure can you suggest some better idea
like DEFINER is = root @ % then i am unable to execute this stored procedure from my local mysql db.

Remove it. Its default added in your stored procedure.

Hi Anvesh,
I am beginner to MYSQL. Could you please throw more light in details on this exception Handling Part? If you have any detailed version of this Please reply with the URL of that article as well.
Many Thanks in Advance.
Regards
Shubhada

Sure, I will update this article and will share few other links.

I am using error handling in my stored proc and it works fine. the results show me only 1 field, the error.

What i am trying to do is call the proc into a reporting software (pentaho). when i call the proc in pentaho it only shows me the error field.

is there i way i can have all the fields i want show up blank and the error message if there is an error?

You can replace that 1 by NULL.

It is a well written article and you have managed to explain a fairly complex feature in simple terms! thanks. it was useful to me.

HI, Below query shows me “No data: 1329 No data – zero rows fetched, selected, or processed”. Cant fix it can u help me.
BEGIN
DECLARE from_date DATETIME;
DECLARE to_date DATETIME;
DECLARE hostname VARCHAR(50);
DECLARE servicename VARCHAR(50);
DECLARE running_no INT;
DECLARE loop_no INT;
DECLARE value1 FLOAT;
DECLARE value2 FLOAT;
DECLARE value3 FLOAT;
DECLARE state INT;
DECLARE logdate DATETIME;
DECLARE prev_status INT;
DECLARE c1len INT;
DECLARE c2len INT;
DECLARE c2flag INT;
DECLARE IsError INT;
DECLARE c1 CURSOR FOR SELECT host_name as host,service_name as service FROM cmp_warehouse.tbl_health_events_csv GROUP BY host_name,service_name ORDER BY host_name, service_name;

SET running_no = 1;
OPEN c1;
set c1len = (SELECT FOUND_ROWS());
l_c1:LOOP

Источник

Smartadm.ru
Adblock
detector