用于 SQL 插入的 PHP Try and Catch

Posted

技术标签:

【中文标题】用于 SQL 插入的 PHP Try and Catch【英文标题】:PHP Try and Catch for SQL Insert 【发布时间】:2010-12-27 11:29:50 【问题描述】:

我的网站上有一个页面(高流量),在每次页面加载时都会插入。

如果系统无法插入 mysql,我很好奇(捕获错误)并继续的最快和最安全的方法。我应该使用 try/catch 还是 die 或其他东西。我想确保插入发生,但如果由于某种原因它不能,我希望页面继续加载。

...
$db = mysql_select_db('mobile', $conn);
mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'") or die('Error #10');
mysql_close($conn);
...

【问题讨论】:

关于“或死”的使用:phpfreaks.com/blog/or-die-must-die 至于异常与检查返回值,这取决于有多少点可能会产生错误。有了一两点,我会进行错误检查,因为在这种情况下它的性能更高并且可读性更高。一旦你在一个代码块中进行了三个或更多的错误检查,异常就会变得更具可读性。这一切都是为了降低圈复杂度。请注意,这涵盖了您处理错误的要点;如果你谈论的是信号错误,你会得到不同的指导。 【参考方案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));        

如果发生错误,你会得到这样的->


    "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\"" 

状态码:409。

【讨论】:

错误拼写错误。 “查询错误”【参考方案2】:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

我不确定是否有 mysql 版本,但添加这行代码允许抛出 mysqli_sql_exception。 我知道,经过了很长时间,问题已经被检查回答,但我得到了不同的答案,它可能会有所帮助。

【讨论】:

是的,您可能有不同的答案。请在答案中添加更多详细信息,例如在哪里添加代码行和详细解释代码的链接? 只要在 php 文件中使用它就可以捕获 mysqli_sql_exceptionS。 因为 mysql 已在 PHP 7.0 中删除,所以应该/需要使用 mysqli 的东西。另请参阅此处的答案以及更多解释:***.com/questions/14578243/…【参考方案3】:
    $sql = "INSERT INTO   customer(FIELDS)VALUES(VALUES)";
    mysql_query($sql);
    if (mysql_errno())
    
            echo "<script>alert('License already registered');location.replace('customerform.html');</script>";
       

【讨论】:

【参考方案4】:

您可以自行实现在 mysql 查询失败时抛出异常。您需要为 mysql_query 函数编写一个包装器,例如:

// 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();

【讨论】:

@Anonymous,这里有一个稍微不同的方法——你只是抛出一个通用的异常,你不知道抛出了哪种异常。当然,您可以将errno 传递为$codeException 的第二个参数)并在catch 块中检查它,但这并不全面。这就是为什么我写了这个答案,尽管这个问题已经有 2 个答案,利用包装器为 mysql_query throwing expcetion。所以,是的,它是相似的,但在概念上并不完全相同。 我明白,你的理解错误的类型,而我的只是为了易于使用。 :) easy of use 是如此依赖于人的术语。我宁愿使用我的代码(实际上我有自己的ORM,但也有自己的例外),尤其是在大型项目中,因为它是ease of use。由于ease of use,John Doe 可以采用您的解决方案。我们都可以选择最适合我们需求的解决方案,对吧?【参考方案5】:

详细说明yasaluyari 的回答我会坚持这样的:

我们可以修改我们的mysql_query如下:

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

现在我们可以像这样简单地使用它,一些很好的例子:

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();

注意它有多美。每当任何 qq 失败时,我们都会遇到错误。您还可以注意到,我们现在不需要将写入查询的状态存储到$result 变量中进行验证,因为我们的函数现在自己处理它。和它处理选择的方式一样,它只是将结果分配给一个变量,就像普通函数一样,但在自身内部处理错误。

另外请注意,我们不需要显示实际错误,因为它们具有巨大的安全风险,尤其是对于这个过时的扩展程序。这就是为什么我们的默认设置在大多数情况下都很好。然而,如果我们确实想通知用户某些特定的查询错误,我们总是可以传递第二个参数来显示我们的自定义错误消息。

【讨论】:

【参考方案6】:

检查documentation 表明它在错误时返回false。所以使用返回状态而不是or die()。如果失败,它将返回 false,您可以记录(或任何您想做的事情)然后继续。

$rv = mysql_query("INSERT INTO redirects SET ua_string = '$ua_string'");
if ( $rv === false )
     //handle the error here

//page continues loading

【讨论】:

我不认为mysql_query会抛出异常。 确实,mysql_querymysqli_query 都不会抛出异常。 PDOStatement::execute 会,但前提是您在调用 PDOStatement::execute 之前先调用 PDO::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)【参考方案7】:

这可以解决问题,

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());

【讨论】:

我原则上不是[或死]的粉丝。【参考方案8】:

如果你想记录错误等,你应该使用 try/catch,如果你不这样做;只需将@放在mysql_query之前

编辑: 你可以像这样使用try catch;这样您就可以记录错误并让页面继续加载

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; 

【讨论】:

mysql 函数没有抛出任何异常。 很好的例子,这似乎是最合适的方法,我也会坚持下去。优势是显而易见的——你会意识到你必须在一个块中执行 5 个查询,如果其中任何一个因异常而失败,你就会滚蛋。不过我会详细说明一下。 好例子和好方法,我的案例的结果:例如:异常 'Exception' 带有消息 'Duplicate entry '4' for key 'PRIMARY'' in 。谢谢【参考方案9】:

使用上一篇文章中描述的任何方法以某种方式捕获 mysql 错误。 最常见的是:

$res = mysql_query('bla');
if ($res===false) 
  //error
  die();

//normal page

这也可以:

function error() 
  //error
  die()

$res = mysql_query('bla') or error();
//normal page

try ... catch Exception $e) .... 不起作用!

注意:与您的问题没有直接关系,但我认为如果您向用户展示一些有用的东西会更好。我永远不会重新访问只显示空白屏幕或任何神秘错误消息的网站。

【讨论】:

以上是关于用于 SQL 插入的 PHP Try and Catch的主要内容,如果未能解决你的问题,请参考以下文章

dbu query PHP函数,用于使用ADOdb库进行ddbb查询(插入查询)

添加filter_var后,PHP代码在SQL表中插入空值

php sql 异常判断

yum安装升级php,mysql报错:epel. Please verify its path and try again

哪个是编写用于插入数据的 PHP 代码的更好方法

SQL注入详解