26

I have a page on my website (high traffic) that does an insert on every page load.

I am curious of the fastest and safest way to (catch an error) and continue if the system is not able to do the insert into MySQL. Should I use try/catch or die or something else. I want to make sure the insert happens but if for some reason it can't I want the page to continue to load anyway.

...
$db = mysql_select_db('mobile', $conn);
mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'") or die('Error #10');
mysql_close($conn);
...
meme
  • 11,861
  • 2
  • 19
  • 20
  • On the use of "or die": http://www.phpfreaks.com/blog/or-die-must-die – outis Dec 17 '09 at 00:55
  • 1
    As for exceptions vs checking return values, it depends on how many points might generate errors. With one or two points, I'd go with error checking, as it's more performant and just as readable in this case. Once you hit three or more error checks in a code block, exceptions become more readable. It's all about reducing cyclomatic complexity. Note that this covers the point you handle the error; if you're talking about signaling errors, you'll wind up with different guidelines. – outis Dec 17 '09 at 00:59

10 Answers10

25

Checking the documentation shows that its returns false on an error. So use the return status rather than or die(). It will return false if it fails, which you can log (or whatever you want to do) and then continue.

$rv = mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'");
if ( $rv === false ){
     //handle the error here
}
//page continues loading
Josh
  • 10,961
  • 11
  • 65
  • 108
Yacoby
  • 54,544
  • 15
  • 116
  • 120
  • 1
    I don't think mysql_query throws an exception. – Yacoby Dec 17 '09 at 00:01
  • 8
    Indeed, neither `mysql_query` nor `mysqli_query` throw an exception. `PDOStatement::execute` will, but only if you call `PDO::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)` before calling `PDOStatement::execute`. – outis Dec 17 '09 at 00:53
11

This can do the trick,

function createLog($data){ 
    $file = "Your path/incompletejobs.txt";
    $fh = fopen($file, 'a') or die("can't open file");
    fwrite($fh,$data);
    fclose($fh);
}
$qry="INSERT INTO redirects SET ua_string = '$ua_string'"   
$result=mysql_query($qry);
if(!$result){
    createLog(mysql_error());
}
vkGunasekaran
  • 6,668
  • 7
  • 50
  • 59
10

You can implement throwing exceptions on mysql query fail on your own. What you need is to write a wrapper for mysql_query function, e.g.:

// user defined. corresponding MySQL errno for duplicate key entry
const MYSQL_DUPLICATE_KEY_ENTRY = 1022;

// user defined MySQL exceptions
class MySQLException extends Exception {}
class MySQLDuplicateKeyException extends MySQLException {}

function my_mysql_query($query, $conn=false) {
    $res = mysql_query($query, $conn);
    if (!$res) {
        $errno = mysql_errno($conn);
        $error = mysql_error($conn);
        switch ($errno) {
        case MYSQL_DUPLICATE_KEY_ENTRY:
            throw new MySQLDuplicateKeyException($error, $errno);
            break;
        default:
            throw MySQLException($error, $errno);
            break;
        }
    }
    // ...
    // doing something
    // ...
    if ($something_is_wrong) {
        throw new Exception("Logic exception while performing query result processing");
    }

}

try {
    mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'")
}
catch (MySQLDuplicateKeyException $e) {
    // duplicate entry exception
    $e->getMessage();
}
catch (MySQLException $e) {
    // other mysql exception (not duplicate key entry)
    $e->getMessage();
}
catch (Exception $e) {
    // not a MySQL exception
    $e->getMessage();
}
Lorenz Lo Sauer
  • 23,698
  • 16
  • 85
  • 87
Nemoden
  • 8,816
  • 6
  • 41
  • 65
  • @Anonymous, there is a slightly different approach here - you just throw a generic exception and you don't know which kind of an exception is thrown. Of course you can pass `errno` as `$code` (2nd param for `Exception`) and check it in `catch` block, but it's not that comprehensive. That's why I wrote this answer despite there are already 2 answers on this question exploiting wrapper for `mysql_query` throwing expcetion. So, yes, it's similar, but not exactly the same conceptually. – Nemoden Sep 07 '12 at 03:34
  • I understand, yours comprehends on types of errors, while mine is exclusively for the easy of use. :) – Anonymous Sep 07 '12 at 03:40
  • `easy of use` is so person-dependent term. I'd rather use my code (I actually have my own `ORM` with it's own exceptions), especially in large projects because of it's `ease of use`. John Doe can go with your solution because of `ease of use`. And we both will be right to chose whatever solution fits our needs best, right? – Nemoden Sep 07 '12 at 03:46
  • @Nemoden: shouldn't it be "try { my_mysql_query(..."? – j.c Jun 06 '22 at 07:28
5

if you want to log the error etc you should use try/catch, if you dont; just put @ before mysql_query

edit : you can use try catch like this; so you can log the error and let the page continue to load

function throw_ex($er){  
  throw new Exception($er);  
}  
try {  
mysql_connect(localhost,'user','pass'); 
mysql_select_db('test'); 
$q = mysql_query('select * from asdasda') or throw_ex(mysql_error());  
}  
catch(exception $e) {
  echo "ex: ".$e; 
}
engvrdr
  • 541
  • 2
  • 9
  • mysql function are not throwing any exceptions. – TheHippo Dec 17 '09 at 01:43
  • Great example, this seems to be the most proper way to do it, and I'm going to stick with it too. The advantage is obvious - you will realize when you'll have to do 5 queries in one block and get the hell out if any of them fails with an exception. I would elaborate on that for a bit though. – Anonymous Sep 07 '12 at 02:22
  • Good example and good way, result for my case: ex: exception 'Exception' with message 'Duplicate entry '4' for key 'PRIMARY'' in . Thank you – Phiber Sep 24 '14 at 14:20
3

Elaborating on yasaluyari's answer I would stick with something like this:

We can just modify our mysql_query as follows:

function mysql_catchquery($query,$emsg='Error submitting the query'){
    if ($result=mysql_query($query)) return $result;
    else throw new Exception($emsg);
}

Now we can simply use it like this, some good example:

try {
    mysql_catchquery('CREATE TEMPORARY TABLE a (ID int(6))');
    mysql_catchquery('insert into a values(666),(418),(93)');
    mysql_catchquery('insert into b(ID, name) select a.ID, c.name from a join c on a.ID=c.ID');
    $result=mysql_catchquery('select * from d where ID=7777777');
    while ($tmp=mysql_fetch_assoc($result)) { ... }
} catch (Exception $e) {
    echo $e->getMessage();
}

Note how beautiful it is. Whenever any of the qq fails we gtfo with our errors. And you can also note that we don't need now to store the state of the writing queries into a $result variable for verification, because our function now handles it by itself. And the same way it handles the selects, it just assigns the result to a variable as does the normal function, yet handles the errors within itself.

Also note, we don't need to show the actual errors since they bear huge security risk, especially so with this outdated extension. That is why our default will be just fine most of the time. Yet, if we do want to notify the user for some particular query error, we can always pass the second parameter to display our custom error message.

Anonymous
  • 4,692
  • 8
  • 61
  • 91
2
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

I am not sure if there is a mysql version of this but adding this line of code allows throwing mysqli_sql_exception.
I know, passed a lot of time and the question is already checked answered but I got a different answer and it may be helpful.

starkm
  • 859
  • 1
  • 10
  • 21
  • Yes, you may have different answer. Please add more details to the answer like where to add the line of code and a link explaining the code in detail? – Ram Oct 17 '14 at 00:51
  • As long as it's used in the php file you may be able to catch the mysqli_sql_exceptionS. – starkm Oct 17 '14 at 00:58
  • since _mysql_ has been removed in PHP 7.0 one should/needs to use the _mysqli_ stuff. see also the answers here with some more explanations: https://stackoverflow.com/questions/14578243/turning-query-errors-to-exceptions-in-mysqli – meistermuh Oct 29 '18 at 09:55
1
    $sql = "INSERT INTO   customer(FIELDS)VALUES(VALUES)";
    mysql_query($sql);
    if (mysql_errno())
    {
            echo "<script>alert('License already registered');location.replace('customerform.html');</script>";
    }   
Vishal
  • 816
  • 11
  • 19
0

To catch specific error in Mysqli


$conn = ...;
$q = "INSERT INTO redirects (ua_string) VALUES ('$ua_string')";
if (mysqli_query($conn, $q)) {
    // Successful
}
else {
    die('Mysqli Error: '.$conn->error); // Show Error Complete Description
}

mysqli_close($conn);

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 27 '22 at 15:41
-1

Use any method described in the previous post to somehow catch the mysql error.
Most common is:

$res = mysql_query('bla');
if ($res===false) {
  //error
  die();
}
//normal page

This would also work:

function error() {
  //error
  die()
}
$res = mysql_query('bla') or error();
//normal page

try { ... } catch {Exception $e) { .... } will not work!

Note: Not directly related to you question but I think it would much more better if you display something usefull to the user. I would never revisit a website that just displays a blank screen or any mysterious error message.

TheHippo
  • 61,720
  • 15
  • 75
  • 100
-1
$new_user = new User($user);
$mapper = $this->spot->mapper("App\User");

try{
    $id = $mapper->save($new_user);     
}catch(Exception $exception){

    $data["error"] = true;
    $data["message"] = "Error while insertion. Erron in the query";
    $data["data"] = $exception->getMessage();

    return $response->withStatus(409)
    ->withHeader("Content-Type", "application/json")
    ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));        
}

if error occurs, you will get something like this->

{
    "error": true,
    "message": "Error while insertion. Erron in the query",
    "data": "An exception occurred while executing 'INSERT INTO \"user\" (...) VALUES (...)' with params [...]:\n\nSQLSTATE[22P02]: Invalid text representation: 7 ERROR:  invalid input syntax for integer: \"default\"" }

with status code:409.

Bharat Chhabra
  • 1,686
  • 2
  • 14
  • 20