How do you check if a columns value is null? Example code:
$db = DBCxn::getCxn();
$sql = "SELECT exercise_id, author_id, submission, result, submission_time, total_rating_votes, total_rating_values
FROM submissions
LEFT OUTER JOIN submission_ratings ON submissions.exercise_id=submission_ratings.exercise_id
WHERE id=:id";
$st = $db->prepare($sql);
$st->bindParam(":id", $this->id, PDO::PARAM_INT);
$st->execute();
$row = $st->fetch();
$this->total_rating_votes = $row['total_rating_votes'];
if($this->total_rating_votes == null) // this doesn't seem to work even though there is no record in submission_ratings????
{
...
}
When you connect to the database, you can set some attributes to control how PDO handles Nulls and Empty Strings when they are returned by the database query
PDO::setAttribute (PDO::ATTR_ORACLE_NULLS, $option )
Where $option is one of the following:
PDO::NULL_NATURAL: No conversion.
PDO::NULL_EMPTY_STRING: Empty stringis converted to NULL.
PDO::NULL_TO_STRING: NULL is converted to an empty string.
Isnt it something like that that you want to do?
foreach($row as $r){
if($r->total_rating_votes == null){
//do something
}
Actually you might want to try:
if($r->total_rating_votes == ""){/*do something*/}
Because php might have converted the null value into an empty string, and then it's not actually null, it's ""
Hope this helps!
Thanks for all of your answers. After a bit of experimentation this code solved my problem
$this->total_rating_votes = $row['total_rating_votes'];
if(!isset($this->total_rating_votes)) // this is now true if this record had a NULL value in the DB!!!
{
...
}
Related
I'm using this code and I'm beyond frustration:
try {
$dbh = new PDO('mysql:dbname=' . DB . ';host=' . HOST, USER, PASS);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
catch(PDOException $e)
{
...
}
$stmt = $dbh->prepare('INSERT INTO table(v1, v2, ...) VALUES(:v1, :v2, ...)');
$stmt->bindParam(':v1', PDO::PARAM_NULL); // --> Here's the problem
PDO::PARAM_NULL, null, '', all of them fail and throw this error:
Fatal error: Cannot pass parameter 2 by reference in /opt/...
You need to use bindValue, not bindParam
bindParam takes a variable by reference, and doesn't pull in a value at the time of calling bindParam. I found this in a comment on the PHP docs:
bindValue(':param', null, PDO::PARAM_INT);
P.S. You may be tempted to do this bindValue(':param', null, PDO::PARAM_NULL); but it did not work for everybody (thank you Will Shaver for reporting.)
When using bindParam() you must pass in a variable, not a constant. So before that line you need to create a variable and set it to null
$myNull = null;
$stmt->bindParam(':v1', $myNull, PDO::PARAM_NULL);
You would get the same error message if you tried:
$stmt->bindParam(':v1', 5, PDO::PARAM_NULL);
When using INTEGER columns (that can be NULL) in MySQL, PDO has some (to me) unexpected behaviour.
If you use $stmt->execute(Array), you have to specify the literal NULL and cannot give NULL by variable reference.
So this won't work:
// $val is sometimes null, but sometimes an integer
$stmt->execute(array(
':param' => $val
));
// will cause the error 'incorrect integer value' when $val == null
But this will work:
// $val again is sometimes null, but sometimes an integer
$stmt->execute(array(
':param' => isset($val) ? $val : null
));
// no errors, inserts NULL when $val == null, inserts the integer otherwise
Tried this on MySQL 5.5.15 with PHP 5.4.1
For those who still have problems (Cannot pass parameter 2 by reference), define a variable with null value, not just pass null to PDO:
bindValue(':param', $n = null, PDO::PARAM_INT);
Hope this helps.
I had the same problem and I found this solution working with bindParam :
bindParam(':param', $myvar = NULL, PDO::PARAM_INT);
If you want to insert NULL only when the value is empty or '', but insert the value when it is available.
A) Receives the form data using POST method, and calls function insert with those values.
insert( $_POST['productId'], // Will be set to NULL if empty
$_POST['productName'] ); // Will be to NULL if empty
B) Evaluates if a field was not filled up by the user, and inserts NULL if that's the case.
public function insert( $productId, $productName )
{
$sql = "INSERT INTO products ( productId, productName )
VALUES ( :productId, :productName )";
//IMPORTANT: Repace $db with your PDO instance
$query = $db->prepare($sql);
//Works with INT, FLOAT, ETC.
$query->bindValue(':productId', !empty($productId) ? $productId : NULL, PDO::PARAM_INT);
//Works with strings.
$query->bindValue(':productName',!empty($productName) ? $productName : NULL, PDO::PARAM_STR);
$query->execute();
}
For instance, if the user doesn't input anything on the productName field of the form, then $productName will be SET but EMPTY. So, you need check if it is empty(), and if it is, then insert NULL.
Tested on PHP 5.5.17
Good luck,
Several answers have given examples of what you should do. But they haven't really explained why you should do one of those things.
The bindParam method is meant to be used with something like a loop (or just repeated statements). It binds a variable reference. So something like
$stmt = $dbh->prepare('INSERT INTO t1 (v1) VALUES(:v1)');
$stmt->bindParam(':v1', $i, PDO::PARAM_INT);
for ($i = 0; $i < 10; $i++) {
$stmt->execute();
}
Would insert values 0 through 9 in a table.
That's obviously a very simple example that could be implemented in other, more efficient ways. You could have more complex logic here. But the basic idea is that you bind a reference to a variable and then you can change the value of the variable.
You can get around the need for a reference by creating a variable before calling bindParam. But in your case, you don't particularly want to bind to a variable reference. You just want to bind a value. So go ahead and do exactly that with bindValue.
You can mostly just use bindValue. But to show why both methods exist, let's rewrite the previous example to use bindValue instead of bindParam:
$stmt = $dbh->prepare('INSERT INTO t1 (v1) VALUES(:v1)');
for ($i = 0; $i < 10; $i++) {
$stmt->bindValue(':v1', $i, PDO::PARAM_INT);
$stmt->execute();
}
This will work, but you have to call bindValue on every iteration of the loop whereas you only needed to call bindParam once. But you aren't doing anything like that, so you can just
$stmt->bindValue(':v1', null, PDO::PARAM_INT);
And everything will work, as stated in the accepted answer. Because you want to bind a value, not a variable reference.
Based on the other answers but with a little more clarity on how to actually use this solution.
If for example you have an empty string for a time value but you want to save it as a null:
if($endtime == ""){
$db->bind(":endtime",$endtime=NULL,PDO::PARAM_STR);
}else{
$db->bind("endtime",$endtime);
}
Notice that for time values you would use PARAM_STR, as times are stored as strings.
So you just need to add an extra If statement that properly changes your variable to NULL before you call bindParam(). Here is an example that I figured out for my situation (I was stuck on this for days trying to INSERT a new DB record with a NULL value for one column):
if ($this->companyid == 'NULL' || $this->companyid == NULL) {
$this->companyid = NULL;
$this->companyname = NULL;
$stmt->bindParam(':companyid', $this->companyid);
$stmt->bindParam(':companyname', $this->companyname);
} else {
$stmt->bindParam(':companyid', $this->companyid);
$stmt->bindParam(':companyname', $this->companyname);
}
Try This.
$stmt->bindValue(':v1', null, PDO::PARAM_NULL); // --> insert null
In my case I am using:
SQLite,
prepared statements with placeholders to handle unknown number of fields,
AJAX request sent by user where everything is a string and there is no such thing like NULL value and
I desperately need to insert NULLs as that does not violates foreign key constrains (acceptable value).
Suppose, now user sends with post: $_POST[field1] with value value1 which can be the empty string "" or "null" or "NULL".
First I make the statement:
$stmt = $this->dbh->prepare("INSERT INTO $table ({$sColumns}) VALUES ({$sValues})");
where {$sColumns} is sth like field1, field2, ... and {$sValues} are my placeholders ?, ?, ....
Then, I collect my $_POST data related with the column names in an array $values and replace with NULLs:
for($i = 0; $i < \count($values); $i++)
if((\strtolower($values[$i]) == 'null') || ($values[$i] == ''))
$values[$i] = null;
Now, I can execute:
$stmt->execute($values);
and among other bypass foreign key constrains.
If on the other hand, an empty string does makes more sense then you have to check if that field is part of a foreign key or not (more complicated).
I have maybe a really simple problem for you but it's making me crazy.
In my index.php I call my userHandler to retrieve data from MySQL in this first line of code but whatever I do the $result stays null.
When debugging, I can clearly see that the MySQL returns one row and its not null.
$result = $userHandler->getUserByPhone($phoneNumber);
if ($result != NULL) {
}
Here is the method that returns result:
public function getUserByPhone($Phone) {
$stmt = $this->conn->prepare("SELECT user.* FROM user");
$stmt->execute();
$result = $stmt->get_result();
$num_of_rows = $result->num_rows;
$stmt->store_result();
$stmt->close();
return $result;
}
And here is the screenshot of function
and it returns null
Edit:
Ok i tought that after closing the statement the data would be lost. and thats true if i still want to return the data of the statement. but before closing i stored the data in a variable. and then close it. I checked in debug after closing the variable still has the data.
Then i thought maybe the variable will be set null too (after all im a noob in php i can think none sense :D )
so i only returned True. But its still null in receiving end.
You'd need to pull the data you need out of $result prior to closing the statement. Closing the statement will clear the statement and the related result set, rendering the value null.
Since getUserByPhone should seemingly return a user, I'd suggest that you get the user data out of the result and return that rather than closing the statement then trying to return the mysqli result object.
Something like:
$result = $stmt->get_result();
$user = $result->fetch_assoc();
$stmt->close();
return $user;
There is only one record in my database, and the "action_taken" column is set to NULL. How the hell do I get PDO to find it???
If I type the query directly into SQL it works as expected.
Note: This is just a test script to illustrate my problem. Most the time the value passed will be a string, but occasionally the value will be NULL.
include ('include/mysql.php');
$sql = 'SELECT * FROM returns WHERE action_taken = :action';
$sth = $dbh->prepare($sql);
$param = null;
$sth->bindValue(':action', $param, PDO::PARAM_STR);
$sth->execute();
if ($sth->rowCount())
{
echo 'FOUND YOU!';
}
else
{
echo 'NOOOO :(';
}
Basically, you can't say "equal to null". It always has to be IS null:
$sql = 'SELECT * FROM returns WHERE action_taken IS :action';
You'd be better off not using NULL at all, if at all possible.
I am having trouble binding a null parameter in the following code
$nullVariable = NULL;
$sql = new PDO('mysql:host=' . $Server, $User, $Password);
$sql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$statement = $sql->prepare("SELECT * FROM Table WHERE Binary16Column = :uuid");
$statement->bindParam(":uuid", $nullVariable, PDO::PARAM_NULL);
$statement->execute();
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
The results variable will be a empty array. If I dont use parameters and modify my query to "WHERE Binary16Column IS NULL" it returns the expected number of rows. So the problem must be with how I am handling the parameter, rather than my SQL query.
My code is more complex than listed above, and I need to be able to use a parameter variable which may be null, so checking to see the variable is null and running a different query is less than ideal. Technically I have my own function for setting parameters, this is where I am checking if the contents of the variable is null, and binding the parameter appropriately, so I dont have to write an unnecessary number of queries. The query works also works fine if the variable contains valid data, and the parameter type is PARAM_LOB.
Does anyone know what i'm doing wrong? Thanks a lot!
Read up on three-valued logic. NULL is not a value; it is a marker for the absence of a value, and so NULL can never be equal to anything, including itself.
However, there is a null-safe comparison operator also known as the "spaceship operator," which does consider two nulls to be equivalent.
WHERE Binary16Column <=> :uuid
... should do what you expected.
If you want to select the record with Binary16Column is null, you need to use IS NULL as the condition, but not = NULL.
SELECT * FROM Table WHERE Binary16Column IS NULL
You need to do:
$uuid = /**some value**/;
$sql = new PDO('mysql:host=' . $Server, $User, $Password);
$sql->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
if ($uuid === null) {
$statement = $sql->prepare("SELECT * FROM Table WHERE Binary16Column IS NULL");
} else {
$statement = $sql->prepare("SELECT * FROM Table WHERE Binary16Column = :uuid");
$statement->bindParam(":uuid", $uuid);
}
$statement->execute();
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
I think the reason you are not getting a result because NULL is a keyword. Because of the way MySQL treats NULL values, I think you are going to have to do IS NULL, when you are performing a search for NULL values. I did a bunch of tests in my local database where I have NULL values. The only time that it worked is when I was using IS NULL or IS NOT NULL.
I am sorry I can't be more help (or if I'm just telling you what you already know), but it seems like you are going to have to write separate queries, or perhaps some simple logic to concatenate the appropriate WHERE logic, depending on whether a variable is null or not.
I'm using this code and I'm beyond frustration:
try {
$dbh = new PDO('mysql:dbname=' . DB . ';host=' . HOST, USER, PASS);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8'");
}
catch(PDOException $e)
{
...
}
$stmt = $dbh->prepare('INSERT INTO table(v1, v2, ...) VALUES(:v1, :v2, ...)');
$stmt->bindParam(':v1', PDO::PARAM_NULL); // --> Here's the problem
PDO::PARAM_NULL, null, '', all of them fail and throw this error:
Fatal error: Cannot pass parameter 2 by reference in /opt/...
You need to use bindValue, not bindParam
bindParam takes a variable by reference, and doesn't pull in a value at the time of calling bindParam. I found this in a comment on the PHP docs:
bindValue(':param', null, PDO::PARAM_INT);
P.S. You may be tempted to do this bindValue(':param', null, PDO::PARAM_NULL); but it did not work for everybody (thank you Will Shaver for reporting.)
When using bindParam() you must pass in a variable, not a constant. So before that line you need to create a variable and set it to null
$myNull = null;
$stmt->bindParam(':v1', $myNull, PDO::PARAM_NULL);
You would get the same error message if you tried:
$stmt->bindParam(':v1', 5, PDO::PARAM_NULL);
When using INTEGER columns (that can be NULL) in MySQL, PDO has some (to me) unexpected behaviour.
If you use $stmt->execute(Array), you have to specify the literal NULL and cannot give NULL by variable reference.
So this won't work:
// $val is sometimes null, but sometimes an integer
$stmt->execute(array(
':param' => $val
));
// will cause the error 'incorrect integer value' when $val == null
But this will work:
// $val again is sometimes null, but sometimes an integer
$stmt->execute(array(
':param' => isset($val) ? $val : null
));
// no errors, inserts NULL when $val == null, inserts the integer otherwise
Tried this on MySQL 5.5.15 with PHP 5.4.1
For those who still have problems (Cannot pass parameter 2 by reference), define a variable with null value, not just pass null to PDO:
bindValue(':param', $n = null, PDO::PARAM_INT);
Hope this helps.
I had the same problem and I found this solution working with bindParam :
bindParam(':param', $myvar = NULL, PDO::PARAM_INT);
If you want to insert NULL only when the value is empty or '', but insert the value when it is available.
A) Receives the form data using POST method, and calls function insert with those values.
insert( $_POST['productId'], // Will be set to NULL if empty
$_POST['productName'] ); // Will be to NULL if empty
B) Evaluates if a field was not filled up by the user, and inserts NULL if that's the case.
public function insert( $productId, $productName )
{
$sql = "INSERT INTO products ( productId, productName )
VALUES ( :productId, :productName )";
//IMPORTANT: Repace $db with your PDO instance
$query = $db->prepare($sql);
//Works with INT, FLOAT, ETC.
$query->bindValue(':productId', !empty($productId) ? $productId : NULL, PDO::PARAM_INT);
//Works with strings.
$query->bindValue(':productName',!empty($productName) ? $productName : NULL, PDO::PARAM_STR);
$query->execute();
}
For instance, if the user doesn't input anything on the productName field of the form, then $productName will be SET but EMPTY. So, you need check if it is empty(), and if it is, then insert NULL.
Tested on PHP 5.5.17
Good luck,
Several answers have given examples of what you should do. But they haven't really explained why you should do one of those things.
The bindParam method is meant to be used with something like a loop (or just repeated statements). It binds a variable reference. So something like
$stmt = $dbh->prepare('INSERT INTO t1 (v1) VALUES(:v1)');
$stmt->bindParam(':v1', $i, PDO::PARAM_INT);
for ($i = 0; $i < 10; $i++) {
$stmt->execute();
}
Would insert values 0 through 9 in a table.
That's obviously a very simple example that could be implemented in other, more efficient ways. You could have more complex logic here. But the basic idea is that you bind a reference to a variable and then you can change the value of the variable.
You can get around the need for a reference by creating a variable before calling bindParam. But in your case, you don't particularly want to bind to a variable reference. You just want to bind a value. So go ahead and do exactly that with bindValue.
You can mostly just use bindValue. But to show why both methods exist, let's rewrite the previous example to use bindValue instead of bindParam:
$stmt = $dbh->prepare('INSERT INTO t1 (v1) VALUES(:v1)');
for ($i = 0; $i < 10; $i++) {
$stmt->bindValue(':v1', $i, PDO::PARAM_INT);
$stmt->execute();
}
This will work, but you have to call bindValue on every iteration of the loop whereas you only needed to call bindParam once. But you aren't doing anything like that, so you can just
$stmt->bindValue(':v1', null, PDO::PARAM_INT);
And everything will work, as stated in the accepted answer. Because you want to bind a value, not a variable reference.
Based on the other answers but with a little more clarity on how to actually use this solution.
If for example you have an empty string for a time value but you want to save it as a null:
if($endtime == ""){
$db->bind(":endtime",$endtime=NULL,PDO::PARAM_STR);
}else{
$db->bind("endtime",$endtime);
}
Notice that for time values you would use PARAM_STR, as times are stored as strings.
So you just need to add an extra If statement that properly changes your variable to NULL before you call bindParam(). Here is an example that I figured out for my situation (I was stuck on this for days trying to INSERT a new DB record with a NULL value for one column):
if ($this->companyid == 'NULL' || $this->companyid == NULL) {
$this->companyid = NULL;
$this->companyname = NULL;
$stmt->bindParam(':companyid', $this->companyid);
$stmt->bindParam(':companyname', $this->companyname);
} else {
$stmt->bindParam(':companyid', $this->companyid);
$stmt->bindParam(':companyname', $this->companyname);
}
Try This.
$stmt->bindValue(':v1', null, PDO::PARAM_NULL); // --> insert null
In my case I am using:
SQLite,
prepared statements with placeholders to handle unknown number of fields,
AJAX request sent by user where everything is a string and there is no such thing like NULL value and
I desperately need to insert NULLs as that does not violates foreign key constrains (acceptable value).
Suppose, now user sends with post: $_POST[field1] with value value1 which can be the empty string "" or "null" or "NULL".
First I make the statement:
$stmt = $this->dbh->prepare("INSERT INTO $table ({$sColumns}) VALUES ({$sValues})");
where {$sColumns} is sth like field1, field2, ... and {$sValues} are my placeholders ?, ?, ....
Then, I collect my $_POST data related with the column names in an array $values and replace with NULLs:
for($i = 0; $i < \count($values); $i++)
if((\strtolower($values[$i]) == 'null') || ($values[$i] == ''))
$values[$i] = null;
Now, I can execute:
$stmt->execute($values);
and among other bypass foreign key constrains.
If on the other hand, an empty string does makes more sense then you have to check if that field is part of a foreign key or not (more complicated).