2010-03-23 107 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