I've looked around and have noticed a few people have had the same problem but their oversight doesn't seem to apply here.
I have a PHP function to add an array of values into a table. It first checks whether the values are empty and if so replaces them with NULL, in order to place a null in the table field. Each fields that I'm placing null into allows for null yet places a 0 there instead.
Here's some code:
public static function AddGame($array, $tId)
{
global $db; // Bring DB into scope
// Get IDs from particular names
$locId = $array['fLocation'];
// Ensure empty values are SQL null
$hTeamId = "'{$array['fHomeTeam']}'";
$vTeamId = "'{$array['fVisitTeam']}'";
$hScore = "'{$array['fHomeScore']}'";
$vScore = "'{$array['fVisitScore']}'";
$hHoldFor = "'{$array['fHomeHoldFor']}'";
$vHoldFor = "'{$array['fVisitHoldFor']}'";
// Prepare row for insertion
$row = "'','$tId','$locId',$hTeamId,$vTeamId,'{$array['fDate']}','{$array['fTime']}',$hScore,$vScore,'{$array['fGameType']}',$hHoldFor,$vHoldFor";
$stmt = $db->prepare("INSERT INTO `game` VALUES($row)");
if($stmt->execute()) return true;
else return false;
}
I've debugged this function at various lines and have dumped the $row string and it shows this, which is expected:
'','1','1','21','21','10/10/12','10:30AM','NULL','NULL','pool','NULL','NULL'
Yet when I check the table text type fields literally have the value NULL which is not what I want and also int fields show as 0. If I leave the values blank or as PHP's null then text fields show as empty (or properly null as I'd like) yet the ints still show as 0.
I expect this is only caused due to the way I insert the values indirectly.
Here is the SHOW CREATE TABLE game
CREATE TABLE `game` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tId` int(11) NOT NULL,
`Lid` int(11) NOT NULL,
`hTeamId` int(11) DEFAULT NULL,
`vTeamId` int(11) DEFAULT NULL,
`date` text NOT NULL,
`time` text NOT NULL,
`hScore` int(11) DEFAULT NULL,
`vScore` int(11) DEFAULT NULL,
`type` text NOT NULL,
`hHoldFor` text,
`vHoldFor` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=latin1
UPDATE:
INSERT INTO `game` VALUES('','1','1','','','10/09/12','9:30AM','','','pool','winner of pool A','winner of pool B')
You are physically setting the value of the wanted NULL columns to a string of 'NULL'
NULL != 'NULL'
If you set your table structure for those columns to NULL, you can omit them from your query and they will automatically be NULL on insert.
Do this instead:
if(!empty($hHoldFor)) $hHoldFor = $array['fHomeHoldFor'];
Update
I was looking further into your example and there is a second point of failure.
$row = ... ",'$hHoldFor','$vHoldFor'";
The above line, if you set $hHoldFor = NULL, will insert quotes around NULL, turning it back into a string of NULL.
Try this:
if(!empty($hHoldFor)) $hHoldFor = "'{$array['fHomeHoldFor']}'";
...
$row = ... ",$hHoldFor,$vHoldFor";
This removes the single quotes around this value in the QUERY string and adds them to the variable itself.
Update 2
Here is an SQLFiddle using your schema. It returns NULL for NULL columns. Can you do an echo "INSERT INTOgameVALUES($row)"; and post the output? The issue is PHP is converting the NULL to 'NULL' still somewhere. This will help us get to the bottom of it.
Update 3
The issue is just as thought. Your PHP is inserting a blank string, '', into your database, which is not a NULL value. NULL is of a type, '' is a string with no length.
INSERT INTO `game` VALUES('','1','1','','','10/09/12','9:30AM','','','pool','winner of pool A','winner of pool B')
Try this:
public static function AddGame($array, $tId)
{
global $db; // Bring DB into scope
// Get IDs from particular names
$locId = $array['fLocation'];
// Ensure empty values are SQL null
$hTeamId = (strlen($array['fHomeTeam']) != 0 ? "'{$array['fHomeTeam']}'" : 'NULL');
$vTeamId = (strlen($array['fVisitTeam']) != 0 ? "'{$array['fVisitTeam']}'" : 'NULL');
$hScore = (strlen($array['fHomeScore']) != 0 ? "'{$array['fHomeScore']}'" : 'NULL');
$vScore = (strlen($array['fVisitScore']) != 0 ? "'{$array['fVisitScore']}'" : 'NULL');
$hHoldFor = (strlen($array['fHomeHoldFor']) != 0 ? "'{$array['fHomeHoldFor']}'" : 'NULL');
$vHoldFor = (strlen($array['fVisitHoldFor']) != 0 ? "'{$array['fVisitHoldFor']}'" : 'NULL');
// Prepare row for insertion
$row = "'','$tId','$locId',$hTeamId,$vTeamId,{$array['fDate']}','{$array['fTime']}',$hScore,$vScore,'{$array['fGameType']}',$hHoldFor,$vHoldFor";
$stmt = $db->prepare("INSERT INTO `game` VALUES($row)");
if($stmt->execute()) return true;
else return false;
}
You can't insert 'NULL'. Remove the single quotes around NULL.
Your string
'','1','1','21','21','10/10/12','10:30AM','NULL','NULL','pool','NULL','NULL'
Should look like
'','1','1','21','21','10/10/12','10:30AM',NULL,NULL,'pool',NULL,NULL
You should also define a column list whenever making an INSERT (ie. INSERT INTO table (col1, col2) VALUES ...)
Edit 1
I would recommend looking through your SHOW CREATE TABLE tbl_name
Edit 2
After testing this, I would still say the problem is with how you're inserting the data.
(18,1,1,21,21,'10/10/12','10:30AM',NULL,NULL,'pool',NULL,NULL)
Works.
('18','1','1','21','21','10/10/12','10:30AM','NULL','NULL','pool','NULL','NULL')
Does not work: Incorrect integer value: 'NULL' for column 'hScore' at row 1:
Edit 3
Here is an improved version of your class:
public static function AddGame($array, $tId)
{
global $db; // Bring DB into scope
// Get IDs from particular names
$locId = $array['fLocation'];
// Ensure empty values are SQL null
$hTeamId = empty($array['fHomeTeam']) ? 'NULL' : "'" . $array['fHomeTeam'] . "'";
$vTeamId = empty($array['fVisitTeam']) ? 'NULL' : "'" . $array['fVisitTeam'] . "'";
$hScore = empty($array['fHomeScore']) ? 'NULL' : "'" . $array['fHomeScore'] . "'";
$vScore = empty($array['fVisitScore']) ? 'NULL' : "'" . $array['fVisitScore'] . "'";
$hHoldFor = empty($array['fHomeHoldFor']) ? 'NULL' : "'" . $array['fHomeHoldFor'] . "'";
$vHoldFor = empty($array['fVisitHoldFor']) ? 'NULL' : "'" . $array['fVisitHoldFor'] . "'";
// Prepare row for insertion
$row = "$tId,$locId,$hTeamId,$vTeamId,'{$array['fDate']}','{$array['fTime']}',$hScore,$vScore,'{$array['fGameType']}',$hHoldFor,$vHoldFor";
$stmt = $db->prepare("INSERT INTO game (tId, Lid, hTeamId, vTeamId, date, time, hScore, vScore, type, hHoldFor, vHoldFor) VALUES($row)");
if($stmt->execute()) return true;
else return false;
}
Non-NULL values will be encased in quotes, otherwise they are assigned NULL. I've also defined the column list for INSERT and excluded id, as it's an AUTO_INCREMENT column.
Does you column allows NULL values? Check the DDL again maybe you have set the DEFAULT VALUE to zero.
When you try to insert null value in a column, don not wrap it with single quote. Example
INSERT INTO tableName (colName, ColNameB) VALUES (1, NULL)
In my case i had to display three situations: Case-empty, Case-yes and Case-no. I planned to use null, one and zero. But the null was being saved always as 0. The column i was working accepted null entries but all my nulls was being saved as zeros.
My solution, was considering Case-empty as zero, Case-yes as the number one and case-no as the number two. It is a workaround but solved the problem.
Related
I am copying one complete database to other database. Every thing is working except one problem. Say one of my table has following structure
id -> Integer PK AI
state_id -> Integer (Default NULL)
sell_id -> Integer (Default NULL)
Now this table can have NULL in state_id and sell_id. So I query SELECT to this table, an empty string is return against all NULL values. But when I try to insert these values to other database table, it generates error as empty string cannot be given in integer column. Like select query return data some thing like following array
array(
'id' => 1,
'state_id' => '',
'sell_id' => ''
)
So I will try to insert this array into new table, it will generate error. So I want to replace all '' with NULL. I have tried following by setting NULL to all empty values
$array = array_map(function($v){
return $v == '' ? NULL : $v;
},$array);
But this also prints '' to all NULL values. This is my complete Code
$result = mysqli_query($dbConnection1, "SELECT * FROM $table ORDER BY $sortedBy DESC limit $noOfRecords");
$columns = '';
$values = '';
if($result && mysqli_num_rows($result)) {
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC) ) {
$array = array_values($row);
$array = array_map(function($v){
return $v == '' ? NULL : $v;
},$array);
$columns = " (".implode(", ",array_keys($row)).") ";
$values .= " ('".implode("', '",$array)."'),";
}
$values = rtrim($values, ",");
mysqli_query($dbConnection2, "INSERT INTO $table $columns VALUES $values");
}
But this code isn't working for above stated scenario. The Insert query is printed as
INSERT INTO table (id, state_id, sell_id) VALUES (1, '', '') , (2, '', '')
But I want it to be like
INSERT INTO table (id, state_id, sell_id) VALUES (1, NULL, NULL) , (2, NULL, NULL)
Can any body let me know how can I achieve that in my scenario.
This could easily be done with a single query:
INSERT INTO newtable (newfield1, newfield2, etc...)
SELECT oldfield1, IF(oldfield2="", NULL, oldfield2), etc...
FROM oldtable
The select can correct/adjust any of the field values on-the-fly.
And note that your version is vulnerable to sql injection attacks. Doesn't matter that the data you're dealing with came out of the database just milliseconds before - it's still unquoted/unescaped data and can/will blow up your insert query.
First of all if i need to move some data i do this over only SQL like #MarcB mentioned his answer but if you insist on your method i think you need to change the following line
return $v == '' ? NULL : $v;
to
return $v == '' ? 'NULL' : $v;
With this change your array's null elements becomes php's string 'NULL' so when they implode they wont convert to '' empty string they will still remains as a string NULL so they will appear as NULL in your insert SQL
The query:
UPDATE caption_queue SET status = 'Conversion Completed' WHERE tpi_id = '3130'
As stated in the title, when I run this in PHP, the value is set to an empty string. However, when the exact same query is run directly in MySQL, it works correctly.
On top of that, I'm only getting this behavior on a single enum value: 'Conversion Completed'. When updating with other values (most of which also contain spaces), there is no problem.
Actual PHP code for those interested:
$sql = "UPDATE caption_queue SET status = 'Conversion Completed' WHERE tpi_id = '$tpi_id'";
$val = mysqli_query($link, $sql);
//$link comes from somewhere else, but we use it extensively throughout our website
Table definition:
CREATE TABLE IF NOT EXISTS `caption_queue` (
`tpi_id` int(11) NOT NULL,
`pid` int(6) DEFAULT NULL,
`conversion_began` datetime DEFAULT NULL,
`yt_caption_id` varchar(50) DEFAULT NULL,
`yt_video_id` varchar(50) DEFAULT NULL,
`status` enum('Pending Conversion','Converting','Conversion Completed','Pending Upload','Video Processing','Video Processed','Uploading Transcription','Caption Syncing','Caption Synced','Caption Downloading','Caption Ready') DEFAULT 'Pending Conversion'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
if you are using MySQLI and your database has enums you need to find the place of your value in order to update your database because it does not accept new strings!
here is an example of the column of my database configuration!
status enum('active', 'inactive', 'banned')
if you want to update these values convert the values into numbers for example active = 1, inactive = 2, banned = 3
from PHP we are able to do the following
$query = 'UPDATE '.$this->table.' SET status = :status'
$stmt = $this->conn->prepare($query);
if($this->status == 'active')
{
$finalStatus = 1;
}
if($this->status == 'inactive')
{
$finalStatus = 2;
}
if($this->status == 'banned')
{
$finalStatus = 3;
}
$stmt->bindParam(':status', $finalStatus);
$stmt->execute();
and this will save your day!
this code was used as an example to provide a full solution to this issue!
Thanks.
I think you'll find it should work if you put the column called status in back ticks.
$query="UPDATE caption_queue SET `status` = 'Conversion Completed' WHERE tpi_id = '3130'";
I found a workaround. By using strict mode:
SET SESSION sql_mode = 'STRICT_ALL_TABLES'
I'm able to update the field with no issues. Seems like some kind of issue with mysqli.
I have a csv file i'm trying to write into mysql table.
file.csv
id,name,age,job
5,John Smith,34,Janitor
7,Jane Smith,,Teacher
9,Jim Bob,23,Coach
table
CREATE TABLE `table` (
`id` smallint(3) unsigned NOT NULL,
`name` varchar(30) DEFAULT NULL,
`age` tinyint(3) unsigned DEFAULT NULL,
`job` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
My issue is that the null value for Jane Smith's age is being inserted into my MySQL table as 0, despite the age default being NULL. I'm using the following fgetcsv() PHP.
$f = '/home/file.csv';
$file = fopen($f,'r');
fgetcsv($file); // skips 1st line with headers
while (($data = fgetcsv($file,0,",")) !== FALSE) {
if (array(null) !== $data) {
$id = $data[0];
$name = $data[1];
$age = $data[2];
$job = $data[3];
$bind_params = array(
':id' => $id,
':name' => $name,
':age' => $age,
':job' => $job
);
$stmt = $conn->prepare("INSERT INTO table (id, name, age, job) VALUES (:id, :name, :age, :job)");
$stmt->execute($bind_params);
}
}
I've read http://php.net/manual/en/function.fgetcsv.php and https://dev.mysql.com/doc/refman/5.5/en/load-data.html at length but I can't figure it out. I've substituted "NULL", "", "\N", NULL, and \N between the ,, but I haven't gotten any different results. I've also tried by explicitly typing the optional parameters for fgetcsv() as shown in the example on php.net.
array fgetcsv ( resource $handle [, int $length = 0 [, string $delimiter = "," [, string $enclosure = '"' [, string $escape = "\\" ]]]] )
What am I missing!? Thank you.
Additional Info:
I prefer this be a php/fgetcsv solution and not a pure MySQL solution, as the data above is only a snapshot (there are 99 columns in total) and many of the columns are inputs into php calculations before being inserted into other tables.
Empty values in a csv are read by PHP's fgetcsv() as empty strings, not as true NULL values. Re-assign only those variables that are empty strings (via if() statement) to NULL values before binding variables (for PDO) and inserting into MySQL table.
After input from #u_mulder, I wrapped each variable in an if statement that looks for empty strings, and if empty string is true, then assign that variable value = null. Since I have 99 columns, i'll put this into a for() loop to get all the columns.
for ($i=0; $i<=99; $i++) {
if($data[$i] === "") { $data[$i] = null; }
}
I implemented this, and it worked exactly as I initially needed.
edit
I updated code to use the === instead of just ==. I found that the double equal sign was converting zeros into null values. Since I only wanted exactly empty strings, the third equal sign is needed.
When I insert a NULL into a MYSQL INTEGER field via a PHP prepared statement it inserts as 0.
I have searched for similar questions and have update my code but am still having the problem.
In my code, if a text box sends an empty string to PHP; PHP converts it to NULL ie.
$v3 = (strlen($v3)<1 ) ? NULL : $v3;
As an example, a result in the UNIT column could be NULL.
The prepare statement
$stmt = $mysqli->prepare("INSERT INTO address ( `PERSON`, `TYPE`, `UNIT`, `STREET_NUM`, `STREET`, `STREET_TYPE`, `SUBURB`, `STATE` ) VALUES (?,?,?,?,?,?,?,?)"));
Bind the parameter as an integer
$stmt->bind_param('isiissss',$p, $add_type[$a], $unit[$a], $street_num[$a], $street_name[$a], $street_type[$a], $suburb[$a], $state[$a]);
In MYSQL, address.unit is NULLABLE and has no default value.
If I insert directly into the table and omit a value for the unit column; NULL is stored. Which I expected.
I suspect that the bind_param function changes NULL to 0 if the datatype for the column is specified as 'i' (integer), because NULLs passed to VARCHAR columns are stored as NULL.
Am I correct and if so how should I pass a NULL to the integer column?
To simplify my question (and because I didn't think it would be relevant) I omitted that the values where passing through a $mysqli->real_escape_string function and after some testing I found that it converts a NULL to an empty string
$test = "";
$test = (strlen($test)<1 ) ? NULL : $test;
var_dump($test); // null
echo "<br>";
$test = $mysqli->real_escape_string($test);
var_dump($test); // string '' (length=0)
This does not solve my problem but it does answer this question
I'm trying to insert NULL into the mySQL databse with PHP.
I've got:
$myVariable=$_POST[inputfield];
if(!is_numeric($myVariable) || $myVariable==0){
$myVariable=NULL;
}
My database field is decimal, and IS NULL has been set. It keeps reverting to 0.00 if input is left blank. How do I set NULL if left blank, so I can call a php if NULL function?
Edit Calling if NULL in decimal is not correct?
<? if ($debit==NULL || $debit=="0.00") {echo 'Awaiting Cost';}
elseif ($debit != NULL || $debit!="0.00") { echo "£$debit";}?>
This displays my message correctly, so if if NULL is useless for a decimal i'll just leave 0.00. Is this hacky?
SQL structure for those who asked:
`myTableField` decimal(10,2) default NULL,
If you are composing an SQL statement by appending the value of the $myVariable variable, then you should look if it's NULL or not and modify the SQL statement accordingly.
For example, if your code is something like:
$sql .= "myVariable = '" . mysql_real_escape_string($myVariable) . "'";
then you should change it to something like:
if (is_null($myVariable)) {
$sql .= "myVariable = NULL";
} else {
$sql .= "myVariable = '" . mysql_real_escape_string($myVariable) . "'";
}
Try it on the SQL side:
$sql = "INSERT INTO `table` (`field1`) VALUES (IF($myVariable == 0, NULL, $myVariable))";
try:
$myVariable="NULL";
.
if your code is:
$val=NULL;
mysql_query("SET #v=$val");
the MySQL got the string:
SET #v=0;
it's like using :
echo "SET #v=$val";
you can filter field's data in MySQL itself, using a TRIGGER:
CREATE TRIGGER table1_update BEFORE UPDATE ON table1 FOR EACH ROW SET
NEW.num=IF(NEW.num=0 ,NULL,NEW.num),
NEW.txt=IF(NEW.txt="",NULL,NEW.txt);
CREATE TRIGGER table1_create BEFORE INSERT ON table1 FOR EACH ROW SET
NEW.num=IF(NEW.num=0 ,NULL,NEW.num),
NEW.txt=IF(NEW.txt="",NULL,NEW.txt);