2010-03-23 175 views
8

我在MySQL的某些列上創建了一個包含NOT NULL約束的表。然後在PHP中,我寫了一個腳本來插入數據,插入查詢。當我在此插入語句中省略其中一個NOT NULL列時,我希望MySQL發出錯誤消息,並且我希望我的腳本失敗。相反,MySQL會在NOT NULL字段中插入空字符串。在其他省略字段中,數據爲NULL,這很好。有人能告訴我我在這裏做錯了什麼嗎?MySQL忽略NOT NULL約束

我使用這個表:

CREATE TABLE IF NOT EXISTS tblCustomers (
    cust_id int(11) NOT NULL AUTO_INCREMENT, 
    custname varchar(50) NOT NULL, 
    company varchar(50), 
    phone varchar(50), 
    email varchar(50) NOT NULL, 
    country varchar(50) NOT NULL, 
    ... 
    date_added timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (cust_id) 
) ; 

而這個插入語句:

$sql = "INSERT INTO tblCustomers (custname,company) 
     VALUES ('".$customerName."','".$_POST["CustomerCompany"]."')"; 
$res = mysqli_query($mysqli, $sql); 

或者使用綁定變量:

$stmt = mysqli_prepare($mysqli, "INSERT INTO tblCustomers (custname,company, email, country) VALUES (?, ?, ?, ?)"); 

mysqli_stmt_bind_param($stmt, 'ssss', $customerName, $_POST["CustomerCompany"], $_POST["CustomerEmail"], $_POST["AddressCountry"]); 
mysqli_stmt_execute($stmt); 
mysqli_stmt_close($stmt); 

回答

14

如果你確定你沒有使用明確的默認值,然後檢查你的嚴格模式:

SELECT @@GLOBAL.sql_mode; 
SELECT @@SESSION.sql_mode; 

MySQL Data Type Default Values

自MySQL 5.0。2,如果列 定義包括沒有明確 DEFAULT值時,MySQL確定 默認值如下:

如果列可以採取NULL作爲 值,列被用 明確的DEFAULT NULL子句定義。這是 與5.0.2之前相同。

如果該列不能取NULL作爲 的值,MySQL將定義具有 的列沒有明確的DEFAULT子句。對於數據 條目,如果插入或替換 語句包括用於 列中沒有值,或更新語句設置 列到NULL,MySQL的根據在當時 效果SQL模式處理 柱:

  • 如果沒有啓用嚴格的SQL模式,MySQL會將該列設置爲默認值爲 的列 數據類型。

  • 如果啓用嚴格模式,則事務性表 發生錯誤,並且語句將回滾。對於 非事務性表,將出現錯誤 ,但如果這種情況發生在 多行聲明的第二行或後續行中,則會插入前面的 行。

Server SQL Modes

+0

嚴格模式做到了!謝謝!至少當我省略一個值時,記錄沒有被插入。當$ _POST [「CustomerEmail」]爲空時,該記錄仍然插入,並且爲空字符串,但這不是該問題的範圍。阻止插入空字符串的搜索繼續進行。 – Whakkee 2010-03-24 19:58:52

+0

爲了回答你的第二個問題,你應該使用參數綁定,正如其他答案中所解釋的,但考慮一下。你不需要'。' concat操作符在使用雙引號時生成查詢。您可以執行此操作「VALUES($ customerEmail)」。因此:if(!empty($ _ POST ['CustomerEmail']){$ customerEmail =''$ _POST ['CustomerEmail']'「;} else {$ customerEmail =」NULL「;} – 2010-03-24 20:29:12

+0

感謝您的建議,我已經使用參數綁定,當馬克Byers發佈它時,我改變了我的代碼,並且...我已經做了檢查在PHP方面是否是空的我正在尋找一個數據庫檢查,就像我用於Oracle數據庫的檢查約束。說實話:在Oracle中我不需要檢查約束,因爲在Oracle中空字符串被視爲NULL。在這種情況下,空字符串與NULL一樣不好,所以當我仍然可以插入空字符串,NOT NULL約束對我來說毫無用處,也許我應該發佈一個關於這個的新問題。 – Whakkee 2010-03-25 08:40:10

4

你所做錯了,是構建使用字符串查詢而不是使用綁定參數。

除了SQL注入漏洞之外,甚至在數據庫看到它們之前,空值都被轉換爲空字符串。

$x = null; 
print_r("VALUES ('$x', 42)"); 

輸出:

VALUES ('', 42) 

換句話說,你插入一個空字符串,而不是NULL。要插入你會需要寫一個NULL:如果您使用綁定參數

VALUES (NULL, 42) 

,那麼你不會得到這個問題,作爲獎勵您的網站將不會有那麼多的安全漏洞。我建議你閱讀this question的答案,並按照那裏的建議。這將解決您的直接問題,並改善您的網站的安全性。

+0

我必須承認,使用綁定的參數是更好的,但它並沒有解決我的問題呢。我現在將研究嚴格模式設置... – Whakkee 2010-03-23 22:38:43

1

我同意Mark Byers--你的php對於你想要的行爲是不正確的。

回覆:馬克在綁定參數評論,退房PDO in PHP

如果你還是不希望使用參數,你可以嘗試以下方法:


if (isset($customerName) && $customerName != '') 
{ 
    $c = '\'' . $customerName . '\''; 
} else { 
    $c = 'null'; 
} 

if (isset($_POST['CustomerCompany']) && $_POST['CustomerCompany'] != '') 
{ 
    $cc = '\'' . $_POST['CustomerCompany'] . '\''; 
} else { 
    $cc = 'null'; 
} 

$sql = 'INSERT INTO tblCustomers (custname,company) 
     VALUES ('.$c.','.$cc.')'; 

編輯:你有沒有考慮只需檢查您的PHP代碼以確保值不是首先爲空/空值?這樣,你可以完全避免去數據庫之旅(根據我對你的評論的解釋)?不是真正的MySQL行爲的答案,但可能會解決你的問題。

+0

「&& $ _POST ['CustomerCompany']!=''」是多餘的。如果$ _POST ['CustomerCompany']是一個長度爲零的字符串,isset($ _ POST ['CustomerCompany'])將返回false。 – jmucchiello 2010-03-25 16:12:09