【问题标题】:How do I get NULL into a MySQL integer column with PHP/MySQLi?如何使用 PHP/MySQLi 将 NULL 放入 MySQL 整数列?
【发布时间】:2011-08-13 12:30:09
【问题描述】:

我通过 URL 将值传递到 PHP 页面并在 MySQLi 查询中使用它们。问题是对于整数列,空字符串被转换为零,而实际上它需要为 NULL。

如何使用 PHP/MySQLi 从 URL 中传递的参数将 NULL 放入整数列?

更新: 这是我如何使用传入参数和准备好的语句进行插入的示例。我需要在 DB 上为 NULL 的是 $specialtyType。

function InsertItem($itemID, $ownerID, $specialtyType)
{
    $this->insertItemStmt->bind_param("ssi", $itemID, $ownerID, $specialtyType);
    $this->insertItemStmt->execute();

如果我在 bind_param 之前添加 Jason 建议的行(设置一个中间变量并在 bind_param 中使用它而不是 $specialty_type),它会在 execute() 之后包含 0。

【问题讨论】:

  • 你试过$specialtyType = null吗?
  • 我最终重写了它,以便如果参数应该为空,则根本不会将参数传递给服务器,但我怀疑将其设置为 NULL(不带引号)确实会起作用。跨度>

标签: php mysql mysqli null integer


【解决方案1】:
$int_value = empty($_GET['int_value']) ? NULL : (int)$_GET['int_value'];

使用$int_value 作为INSERT 中的列。

【讨论】:

  • 谢谢,杰森。不幸的是,这没有奏效。我验证了传入的字符串为空,并使用您的语句转换为“NULL”。我在 bind_param 语句中使用了转换后的字符串,但数据库仍然抱怨违反约束。但是,如果我执行一个 SQL INSERT 语句,其中列的值为 NULL,它就可以正常工作。
  • 哇,这是一个毛茸茸的表情!我认为缺少括号导致默认运算符优先级打败了您要完成的工作。我会将其重写为:$int_value = strlen($_GET['int_value']) ? ((int)$_GET['int_value']) : 'NULL';
  • @Oscar,所以INSERT 有效,但bind_param 无效。请发布该代码。 @kmoser,您的重写不是逻辑等价物,因为它允许将空间保存为零而不是 NULL。
  • 我用一些代码更新了我的帖子。现在我已经通过更改客户端代码来解决这个问题,以便在 URL 应该为 null 时完全省略该参数。然后 $_GET['specialtyType'] 什么都不检索并将其发送到上面的函数中,并且 DB 列按预期结束 NULL。杰森,您的行是否可能不应该在“NULL”周围加上引号?
  • 在删除 NULL 周围的引号后,我接受了这个答案。谢谢!
【解决方案2】:

问题不是如何通过 mysqli 向 MySQL 发送 NULL,而是如何从 GET 参数中获取 NULL 值。

我建议两种方法。要么使用filter_input(),这是一个非常方便的函数,要么在 URL 查询中没有传递任何值时提供 null 作为默认值。

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
// or
$id = empty($_GET['id']) ? null : (int) $_GET['id'];

// If no value was presented in GET then $id will be passed as NULL
$stmt->bind_param('s', $id);

在我看来,filter_input() 提供了更正确的结果。查看此比较:

| $_GET['id']   | filter_input | Cast to int |
|---------------|--------------|-------------|
| Inexistent    | false        | NULL        |
|               | NULL         | NULL        |
| <white space> | NULL         | 0           |
| 0             | 0            | NULL        |
| 42            | 42           | 42          |
| 42.333        | NULL         | 42          |

【讨论】:

    【解决方案3】:

    您可能想查看您的数据库架构,以查看相关列是否甚至允许空值。如果该列不允许空值,那么当您尝试输入空值时,它将使用该字段的默认值……对于整数字段,该值通常为零。

    【讨论】:

    • 它允许空值。这是一个外键,它必须是 null 或来自另一个表的有效值。否则,就是违反约束。
    【解决方案4】:

    我遇到了这个问题,只是将相关的 DB 列从 INT 更改为 VARCHAR。空值现在存储为 NULL 并且 0 是 0。即使在 PHP MyAdmin 中删除 0 也会看到一个 '0' 弹出回来,所以我猜 INT 将空值等同于零而 VARCHAR 不是。

    【讨论】:

      【解决方案5】:

      对于 MySQLi,您不能将 NULL 或 0 甚至“NULL”之类的常量作为 bind_param() 参数传递。

      传递的所有内容都必须是引用类型。这是一个愚蠢的限制,我知道。

      但解决它很容易。只需创建一个一次性变量。在我一直从事的项目中,我需要将一些数据插入到 BLOB 字段中。不幸的是,如果二进制数据超过一定长度,MySQLi 不允许您绑定。您必须 绑定 NULL,然后通过 send_long_data() 发送二进制信息。

      但是,再一次,你不能绑定像 NULL 这样的常量,所以在示例中,看看我在哪里使用了变量 $Dummy

      $InfoToInsert = array
      (
          'a number' => 9000,
          'a double' => 9000.0,
          'a string' => 'Hello World',
          'a blob' => gzdeflate('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed')
      );
      $Stmnt =
      (
          'INSERT INTO _mytable '.
              '(_myintcol, _mydoublecol _mystringcol, _myblobcol) '.
          'VALUES '.
              '(?, ?, ?, ?)'
      );
      if(!$PreparedStmnt = $Conn->prepare($Stmnt))
      {
          $OutputError = 'Failure preparing statement: '.my_SanitizeHtml($Conn->error).'<br /><br />Full query:<br />'.$Stmnt;
          $Conn->rollback();
          $Conn->close();
          return(false);
      }
      $Dummy = null;
      $PreparedStmnt->bind_param
      (
          'idsb',                         // Possible types:
                                          //     i for Integer
                                          //     d for Double
                                          //     s for String
                                          //     b for BLOB
      
          $InfoToInsert['a number'],      // _myintcol
          $InfoToInsert['a double'],      // _mydoublecol
          $InfoToInsert['a string'],      // _mystringcol
          $Dummy                          // _myblobcol
      );
      $PreparedStmnt->send_long_data(3, $InfoToInsert['a blob']); // 3 because it's the 4th parameter (-1 for zero-based)
      if(!$PreparedStmnt->execute())
      {
          $OutputError = 'Failure inserting report: '.my_SanitizeHtml($Conn->error);
          $PreparedStmnt->close();
          $Conn->rollback();
          $Conn->close();
          return(false);
      }
      $PreparedStmnt->close();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-26
        • 2014-07-26
        • 2010-11-18
        • 2020-07-22
        • 1970-01-01
        • 2013-12-24
        • 1970-01-01
        • 2017-10-30
        相关资源
        最近更新 更多