简体   繁体   中英

How do I get NULL into a MySQL integer column with PHP/MySQLi?

I'm passing values into a PHP page through the URL and using them in queries with MySQLi. The problem is that an empty string gets converted to zero for an integer column, when in fact it needs to be NULL.

How do I get NULL into an integer column with PHP/MySQLi, from a param passed in the URL?

Update: Here's an example of how I'd use the incoming parameter and a prepared statement to do the insert. The one I need to be NULL on the DB is $specialtyType.

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

If I add Jason's suggested line before the bind_param (setting up an intermediate variable and using it in the bind_param instead of $specialty_type), it winds up containing 0 after the execute().

$int_value = empty($_GET['int_value']) ? NULL : (int)$_GET['int_value'];

$int_value用于INSERT的列。

The question is not how to send NULL to MySQL via mysqli, but rather how to get NULL value from the GET parameters.

I would suggest two ways. Either use filter_input() which is a really handy function or provide null as a default value if no value was passed in the URL query.

$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);

In my opinion filter_input() provides more correct outcome. See this comparison:

| $_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          |

I had this problem and just changed the relevant DB columns from INT to VARCHAR. Empty values are now stored as NULL and a 0 is a 0. Even deleting the 0 in PHP MyAdmin would see a '0' pop back up, so I guess INT equates empty with zero and VARCHAR doesn't.

Normally, you add regular values to mySQL, from PHP like this:

function addValues($val1, $val2) {
    db_open(); // just some code ot open the DB 
    $query = "INSERT INTO uradmonitor (db_value1, db_value2) VALUES ('$val1', '$val2')";
    $result = mysql_query($query);
    db_close(); // just some code to close the DB
}

When your values are empty/null ($val1=="" or $val1==NULL), and you want NULL to be added to SQL and not 0 or empty string, to the following:

function addValues($val1, $val2) {
    db_open(); // just some code ot open the DB 
    $query = "INSERT INTO uradmonitor (db_value1, db_value2) VALUES (".
        (($val1=='')?"NULL":("'".$val1."'")) . ", ".
        (($val2=='')?"NULL":("'".$val2."'")) . 
        ")";
    $result = mysql_query($query);
    db_close(); // just some code to close the DB
}

Note that null must be added as "NULL" and not as "'NULL'" . The non-null values must be added as "'".$val1."'", etc.

Hope this helps, I just had to use this for some hardware data loggers, some of them collecting temperature and radiation, others only radiation. For those without the temperature sensor I needed NULL and not 0, for obvious reasons ( 0 is an accepted temperature value also). The data is then used to plot some charts, available here .

You might want to look at your database schema to see if the column in question even allows for null values. If the column does not allow nulls, than it will use the default value for the field when you try to put in a null value… which is usually zero for integer fields.

For MySQLi, you can't pass a constant like NULL or 0 or even "NULL" as a bind_param() argument.

Everything passed must be a reference type. It's a stupid limitation, I know.

But working around it is easy. Just create a throw-away variable. In a project I have been working on, I needed insert some data to a BLOB field. Unfortunately, MySQLi doesn't let you bind binary data if it's longer than a certain length. You have to bind NULL and then follow-up with sending the binary info via send_long_data() .

But, again, you cannot bind a constant like NULL, so in the example, look where I used the variable $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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM