MySQL忽略了NOT NULL约束

时间:2010-03-23 21:20:29

标签: php mysql constraints

我在MySQL中的某些列上创建了一个带有NOT NULL约束的表。然后在PHP中我编写了一个插入数据的脚本,带有插入查询。当我省略这个insert语句中的NOT NULL列之一时,我会期望来自MySQL的错误消息,我希望我的脚本失败。相反,MySQL在NOT NULL字段中插入空字符串。在其他省略的字段中,数据为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);

3 个答案:

答案 0 :(得分:16)

如果您确定没有使用显式默认值,请检查严格模式:

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子句。对于数据   输入,如果是INSERT或REPLACE   声明中没有任何价值   列,或UPDATE语句集   列为NULL,MySQL处理   列根据SQL模式而定   当时效果:

     
      
  • 如果未启用严格的SQL模式,MySQL会将列设置为   列的隐式默认值   数据类型。

  •   
  • 如果启用了严格模式,则事务表会发生错误   并且该声明被回滚。对于   非交易表,一个错误   发生,但如果发生这种情况   a的第二行或后续行   多行语句,前面的   将插入行。

  •   

Server SQL Modes

答案 1 :(得分:4)

你做错了是使用字符串而不是使用绑定参数来构建查询。

除了SQL注入漏洞之外,即使在数据库看到它们之前,空值也会被转换为空字符串。

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

输出:

VALUES ('', 42)

换句话说,您正在插入一个空字符串,而不是NULL。要插入NULL,您需要编写此代码:

VALUES (NULL, 42)

如果您使用绑定参数,那么您将不会遇到此问题,作为奖励,您的网站将不会有这么多安全漏洞。我建议你阅读this question的答案,并按照那里的建议。这将解决您的直接问题,并提高您网站的安全性。

答案 2 :(得分:1)

我同意Mark Byers - 你的php对你想要的行为不正确。

Re:Mark对绑定参数的评论,请查看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行为的答案,但可能会解决您的问题。