2011-08-31 90 views
1

操作:創建表記錄,該記錄是唯一鍵上的副本。PHP MySQL在唯一索引上創建重複記錄奇怪失敗

好:獨特的鍵正在工作,因爲沒有創建重複記錄。

不好:我在PHP中使用的mysqli函數沒有按我期望的方式失敗。

Meta:我有一些PHP(運行5.3.6),它處理從AJAX POST請求在Mysql(5.5.9)表中創建新記錄。身份驗證和輸入清理和驗證在我分享的代碼範圍之外處理。響應函數還處理以有效格式輸出響應。我插入的表格有一個自動遞增的id列和一個唯一的名稱列。

// connect to server 
$mysqli = new mysqli("localhost", "dbuser", 'dbpassword', "database"); 
if(mysqli_connect_errno()) { 
    $response["message"] = "unable to connect to the MySQL server at 'localhost' as 'dbuser' using a password or select the database 'database' because ".mysqli_connect_errno(); 
    respond($response); 
} 

// build and run query 
if ($stmt = $mysqli -> prepare("INSERT INTO `database`.`table` (`id`, `name`) VALUES (NULL, ?);")) { 
    $stmt -> bind_param("s", $inputs["name"]); 
    $success = $stmt -> execute(); 
    if ($success) { 
     $response["status"] = "success"; 
     $response["id"] = $mysqli -> insert_id; 
     respond($response); 
    } else { 
     $response["message"] = "failed to insert because ".$stmt -> error; 
    } 

    $stmt -> close(); 
} else { 
    $response["message"] = "unable to build query because ".$mysqli -> error; 
    respond($response); 
} 

$mysqli -> close(); 

可正常工作插入一個新的獨特的名稱時,但試圖插入新的重複名稱時不返回任何東西。我預計

$stmt -> execute(); 

失敗,所以我會返回一個解釋錯誤的迴應。這段代碼沒有這樣做。我發現的唯一方法,返回創建失敗,因爲重複是這樣的緊密語句前加上兩行代碼:

// connect to server 
$mysqli = new mysqli("localhost", "dbuser", 'dbpassword', "database"); 
if(mysqli_connect_errno()) { 
    $response["message"] = "unable to connect to the MySQL server at 'localhost' as 'dbuser' using a password or select the database 'database' because ".mysqli_connect_errno(); 
    respond($response); 
} 

// build and run query 
if ($stmt = $mysqli -> prepare("INSERT INTO `database`.`table` (`id`, `name`) VALUES (NULL, ?);")) { 
    $stmt -> bind_param("s", $inputs["name"]); 
    $success = $stmt -> execute(); 
    if ($success) { 
     $response["status"] = "success"; 
     $response["id"] = $mysqli -> insert_id; 
     respond($response); 
    } else { 
     $response["message"] = "failed to insert because ".$stmt -> error; 
    } 

    $stmt -> close(); 
} else { 
    $response["message"] = "unable to build query because ".$mysqli -> error; 
    respond($response); 
} 

$response["message"] = "Duplicate"; 
respond($response); 

$mysqli -> close(); 

我不明白的事情是當查詢運行作爲預計,重複的響應不會返回。當查詢因嘗試在唯一鍵上插入副本而失敗時,將返回重複的響應。

問題:爲什麼一個成功的插入不能在代碼塊的末尾運行響應函數?

問題:爲什麼插入失敗是因爲嘗試在唯一鍵上插入重複項而不會引發異常或按我的預期失敗?

我也嘗試在try catch塊中包裝整個東西,但它沒有任何幫助,因爲它沒有拋出任何異常。如果你能解決這個問題,我將不勝感激。

回答

3

問題:爲什麼成功的插入不能在代碼塊的末尾運行響應函數?

我假設你respond方法中有一個exitdie的地方,暫停執行。

問題:爲什麼插入失敗的插入是因爲嘗試在唯一鍵上插入副本而不會引發異常或失敗,如我所料?

我認爲這與您的if聲明中的邏輯有關。

如果你的程序不斷進入無響應不斷髮送else語句

$response["message"] = "failed to insert because ".$stmt -> error; 

(該respond函數永遠不會被調用)。你的第二個例子工作的原因是因爲代碼每次都達到這個點(因爲它在最後的else聲明之外)。如果你在上面的行之後將呼叫移動到respond,你可能會發現它會按預期返回消息。以下內容:

// connect to server 
$mysqli = new mysqli("localhost", "dbuser", 'dbpassword', "database"); 
if(mysqli_connect_errno()) { 
    $response["message"] = "unable to connect to the MySQL server at 'localhost' as 'dbuser' using a password or select the database 'database' because ".mysqli_connect_errno(); 
    respond($response); 
} 

// build and run query 
if ($stmt = $mysqli -> prepare("INSERT INTO `database`.`table` (`id`, `name`) VALUES (NULL, ?);")) { 
    $stmt -> bind_param("s", $inputs["name"]); 
    $success = $stmt -> execute(); 
    if ($success) { 
     $response["status"] = "success"; 
     $response["id"] = $mysqli -> insert_id; 
     respond($response); 
    } else { 
     $response["message"] = "failed to insert because ".$stmt -> error; 
     respond($response); // <-- this is the bit you need 
    } 

    $stmt -> close(); 
} else { 
    $response["message"] = "unable to build query because ".$mysqli -> error; 
    respond($response); 
} 

$mysqli -> close(); 
+0

得到錯誤信息,在這裏,我在想,我快要瘋了果然我錯過了調用回覆功能感謝您的幫助。有時候最好只是走開,稍後再看看,謝謝你幫助我。 –

+1

沒問題,恰巧t o我們最好的:) – phindmarsh

1

嘗試從$stmt->errorCode()$stmt->errorInfo()