2009-12-16 62 views
19

我有我的網站(高流量),做每個頁面加載的插件的頁面。PHP try和catch爲SQL插入

我很好奇的最快和最安全的方式(捕獲錯誤),並繼續如果系統無法做到插入到MySQL。我應該使用try/catch還是死或別的什麼。我想確保插入發生,但如果由於某種原因它不能我希望頁面繼續加載。

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

關於使用「或死」:http://www.phpfreaks.com/blog/or-die-must-die – outis 2009-12-17 00:55:14

+1

至於異常與檢查返回值,它取決於有多少點可能會產生錯誤。有一點或兩點,我會去錯誤檢查,因爲它更高性能,並在這種情況下可讀性。一旦您在代碼塊中進行了三次或更多次錯誤檢查,異常變得更具可讀性。這是關於減少圈複雜度。請注意,這涵蓋了您處理錯誤的點;如果你在談論信號錯誤,你會得到不同的指導方針。 – outis 2009-12-17 00:59:57

回答

23

檢查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 
+0

那不會拋出一個錯誤? – 2009-12-16 23:56:21

+1

我不認爲mysql_query引發異常。 – Yacoby 2009-12-17 00:01:02

+8

的確,「mysql_query」和「mysqli_query」都不會引發異常。只有在調用PDOStatement :: execute之前調用PDO :: setAttribute(PDO :: ATTR_ERRMODE,PDO :: ERRMODE_EXCEPTION),'PDOStatement :: execute'纔會執行。 – outis 2009-12-17 00:53:08

5

,如果你想記錄錯誤等你應該使用try/catch語句,如果你沒有;只是把@的mysql_query前

編輯: 您可以使用嘗試捕捉這樣的;所以你可以記錄錯誤並讓頁面繼續加載

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; 
} 
+0

mysql函數不會拋出任何異常。 – TheHippo 2009-12-17 01:43:01

+0

很好的例子,這似乎是最合適的方式,我也會堅持下去。好處是顯而易見的 - 你會意識到,當你必須在一個塊中執行5個查詢時,如果任何一個塊出現異常,它們將會失敗。不過我會詳細闡述一下。 – Anonymous 2012-09-07 02:22:38

+0

好的例子和好的方法,結果爲我的情況:例如:異常'例外'與消息'重複輸入'4'關鍵'PRIMARY''in。謝謝 – Phiber 2014-09-24 14:20:44

-1

使用前一篇文章中描述的任何方法來捕獲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) { .... }都不行!

注:不直接,而是與你的問題,我認爲它會更更好,如果你顯示有用的東西給用戶。我絕不會重新訪問一個只顯示空白屏幕或任何神祕錯誤信息的網站。

10

這可以做的伎倆,

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()); 
} 
+0

這很好。 – 2012-02-22 11:51:25

+0

@DjangoReinhardt謝謝,我很樂意幫助別人... – VKGS 2012-02-23 04:52:10

+0

@Sekar棘手.. – 2013-02-19 06:29:54

2

在闡述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失敗,我們gtfo與我們的錯誤。而且你還可以注意到,我們現在不需要爲編寫查詢的狀態存儲到用於驗證的$result變量,因爲我們的函數現在自己處理吧。同樣,它處理選擇,它只是將結果賦值給一個變量,就像正常函數一樣,但是卻處理了它本身的錯誤。

另外請注意,我們不需要顯示實際的錯誤,因爲他們承受巨大的安全隱患,尤其如此這種過時的擴展。這就是爲什麼我們的默認情況在大多數情況下都會很好。但是,如果我們想要通知用戶某些特定的查詢錯誤,我們總是可以傳遞第二個參數來顯示我們的自定義錯誤消息。

6

你可以在你自己的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(); 
} 
+0

大聲笑,我在10分鐘前做出了類似的回答。 – Anonymous 2012-09-07 03:26:32

+0

@匿名,這裏有一個稍微不同的方法 - 你只是拋出一個泛型的異常,你不知道拋出哪種異常。當然,你可以將'errno'作爲'$ code'傳遞(第二個參數爲'Exception'),並在'catch'塊中檢查它,但並不全面。這就是爲什麼我寫了這個答案,儘管這個問題已經有2個答案利用'mysql_query'的包裝引發expcetion。所以,是的,它是相似的,但概念上不完全一樣。 – Nemoden 2012-09-07 03:34:09

+0

我明白,你瞭解錯誤類型,而我的專用易於使用。 :) – Anonymous 2012-09-07 03:40:29

0
$sql = "INSERT INTO customer(FIELDS)VALUES(VALUES)"; 
    mysql_query($sql); 
    if (mysql_errno()) 
    { 
      echo "<script>alert('License already registered');location.replace('customerform.html');</script>"; 
    } 
0
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); 

我不知道是否有這方面的一個MySQL版本,但加入這一行的代碼允許扔mysqli_sql_exception。
我知道,通過了很多時間,問題已經檢查回答,但我得到了不同的答案,它可能會有所幫助。

+0

是的,你可能有不同的答案。請在答案中添加更多細節,例如添加代碼行以及詳細說明代碼的鏈接? – Ram 2014-10-17 00:51:28

+0

只要它在php文件中使用,您可以捕捉到mysqli_sql_exceptionS。 – starkm 2014-10-17 00:58:29