用于 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
传递为$code
(Exception
的第二个参数)并在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_query
和 mysqli_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查询(插入查询)
yum安装升级php,mysql报错:epel. Please verify its path and try again