在 mysqli 准备好的语句中使用空值

Posted

技术标签:

【中文标题】在 mysqli 准备好的语句中使用空值【英文标题】:using nulls in a mysqli prepared statement 【发布时间】:2010-09-27 03:56:32 【问题描述】:

mysqli 准备好的语句中,NULL 变成 ''(在字符串的情况下)或 0(在整数的情况下)。我想将其存储为真正的 NULL。有没有办法做到这一点?

【问题讨论】:

我不敢相信我已经为此苦苦挣扎了多久,答案几乎是显而易见的。严格地说:你不能。结构上:bind_param。通过代码:$query_param_01 = (null===$param_01) ? "?" : "NULL"; 给所有人 +1。 (我会坚持使用$query_param_01,因为仍然没有注入问题。请随时纠正。 【参考方案1】:

我将所有参数存储在一个数组中,并使用array_shift($myArray) 将它们传递给bind_param 函数。 NULL 是这样接受的。

【讨论】:

【参考方案2】:

可以将真正的 NULL 值绑定到准备好的语句(阅读 this)。

实际上,您可以使用 mysqli_bind_parameter 将 NULL 值传递给数据库。只需创建一个变量并将 NULL 值(参见手册页)存储到变量并绑定它。无论如何对我来说都很好。

因此它必须是这样的:

<?php
    $mysqli = new mysqli('localhost', 'my_user', 'my_password', 'world');

    // person is some object you have defined earlier
    $name = $person->name();
    $age = $person->age();
    $nickname = ($person->nickname() != '') ? $person->nickname() : NULL;

    // prepare the statement
    $stmt = $mysqli->prepare("INSERT INTO Name, Age, Nickname VALUES (?, ?, ?)");

    $stmt->bind_param('sis', $name, $age, $nickname);
?>

这应该在数据库中插入一个 NULL 值。

【讨论】:

很好,正是我需要知道的,只是让它更通用一点:foreach($param as $k =&gt; $v) if($v == '') $param[$k] = NULL; ,所以基本上任何 null 条目都会转换为真正的 NULL,但要小心嵌套数组,只需让它递归如果你使用那些^^虽然这应该是选择的答案,thks【参考方案3】:

PHP documentation on mysqli_stmt::bind_param 的 cmets 表明传入NULL 并不容易。


请看@creatio 的回答:https://***.com/a/6892491/18771


cmets 中提供的解决方案对准备好的语句进行了一些预先准备工作,将具有 PHP null 值的每个参数的 "?" 标记替换为 "NULL"。然后使用修改后的查询字符串。

以下函数来自user comment 80119:

function preparse_prepared($sQuery, &$saParams)

    $nPos = 0;

    $sRetval = $sQuery;
    foreach ($saParams as $x_Key => $Param)
    
        //if we find no more ?'s we're done then
        if (($nPos = strpos($sQuery, '?', $nPos + 1)) === false)
        
            break;
        

        //this test must be done second, because we need to 
        //increment offsets of $nPos for each ?.
        //we have no need to parse anything that isn't NULL.
        if (!is_null($Param))
        
            continue;
        


        //null value, replace this ? with NULL.
        $sRetval = substr_replace($sRetval, 'NULL', $nPos, 1);

        //unset this element now
        unset($saParams[$x_Key]);
    
    return $sRetval;
 

(这不是我真正应该采用的编码风格,但如果它有效的话......)

【讨论】:

FWIW,这会在“WHERE column_name != ?”上中断因为与 NULL 的比较总是 NULL。这也打破了“WHERE question = 'et tu, brute?'”【参考方案4】:
<?php
$mysqli=new mysqli('localhost','root','','test');
$mysqli->query("CREATE TABLE test_NULL (id int(11))");
if($query=$mysqli->prepare("insert into test_NULL VALUES(?)"))
    $query->bind_param('i',$null); //note that $null is undefined
    $query->execute();
else
    echo __LINE__.' '.$mysqli->error;

?>

【讨论】:

【参考方案5】:

对于任何因为在WHERE 语句中绑定 NULL 时遇到问题而前来查看此问题的人,解决方案如下:

有一个mysqlNULL safe operator一定要用:

&lt;=&gt;

例子:

<?php
$price = NULL; // NOTE: no quotes - using php NULL
$stmt = $mysqli->prepare("SELECT id FROM product WHERE price <=> ?"); // Will select products where the price is null
$stmt->bind_param($price);
?>

【讨论】:

以上是关于在 mysqli 准备好的语句中使用空值的主要内容,如果未能解决你的问题,请参考以下文章

在准备好的语句中使用 LIKE '%$var%' 的正确方法? [mysqli]

如果在循环中使用 MySQLi 准备好的语句,我啥时候调用 bind_param?

MySQLi:使用一个准备好的语句插入多行

如何在mysqli准备好的语句中使用SQL LIKE子句[重复]

什么时候在 PHP Mysqli 中使用准备好的语句? - 用户表单搜索输入与选择查询

如何使用mysqli准备好的语句?