Inserting PHP float/decimal values into MySQL - php

It's a pretty simple question to be honest. I've been looking for a while now on Google for a solution but nothing seems to work. I have the following field in my database:
decimal(2,1)
I have two variables in PHP (which come from values inserted into a form via POST) I want to add together and then insert into this field.
$sql2 = $link->prepare("INSERT INTO league_stats (match_id, rating)
VALUES (?, ?)");
$sql->bind_param("ii", $match_id, $rating);
$match_id = $_SESSION["match_id"];
$rtg1 = $_POST[$rating_1"];
$rtg2 = $_POST[$rating_2"] / 10;
$rating = $rtg1 + $rtg2;
For example, rtg1 would be 7 and rtg2 would be 3 divided by 10 so it comes out as 0.3. I then add these two numbers together to make 7.3. When I go to insert it into the database, it always displays the second digit as 0. So instead of 7.3 it would come out as 7.0. I've tried many different methods but I always get the exact same result.
I even assigned $rating to a raw value just to test if there was something wrong with my variables:
$rating = 7.5
Still comes out as 7.0.
Could somebody please provide an example of how to correctly insert a float type PHP variable into MySQL? And also maybe explain how to correctly add two float values together? Thanks!

You are telling php to cast $match_id and $rating to integer. You should use:
$sql->bind_param("id", $match_id, $rating);
instead of
$sql->bind_param("ii", ...

Related

For loop stopping before get to number needed

My idea is to make tooltip for new users on website. They will go through the tooltips and each time they complete a tooltip it inserts into DB.
However i've got a button which is skip all. So my idea is to insert all the reminder tooltips which they've not completed into the DB with for loop.
So it works if there has been no tooltips clicked already. So the tooltip would be equal to 1 because coming through the $data is equal to 0. However if the tooltip is equal to 1 when passed through $data it gets a +1 and the for loop doesn't seem to post anything into database
$NumberOfTooltips = 2;
(int)$data->tooltipLastID = ((int)$data->tooltipLastID === 0) ? 1 : (int)$data->tooltipLastID + 1;
for ($x = (int)$data->tooltipLastID; $x <= $NumberOfTooltips; $x++) {
$query = "";
$query = "INSERT INTO tooltips ";
$query .= "(tooltip_id, inserted) VALUES ($x, NOW())";
database::query($query);
$this->id = database::getInsertID();
}
On the broken loop the value of (int)$data->tooltipLastID is 2
Is it because the (int)$data->tooltipLastID is already equal to $NumberOfTooltips?
General improvements
These do not directly solve the question asked but they do give you a helping hand in clarifying your data and steaming out any secondary bugs and bloopers. Also pointing out some best (or at least, better) practise.
$x is a lazy and poorly defined counter. Prefer using descriptve veraibles such as $tooltipCounter
$data->tooltipLastID should not start at 1; use the same syntax as every other integer number system in PHP/programming and start at zero. If you need a one then add +1 only when it's needed (VALUES (".$x+1.")).
$NumberOfTooltips = 2; The number 2 is probably not high enough for adequate testing.
var_dump($data->tooltipLastID) and var_dump($NumberOfTooltips) to check both values are what you expect.
Rewrite the test code to take the variables out of the code so that you can check your Database connction works correctly (such as if you're trying to insert into a string field-type by mistake)
$query = ""; is redundant.
You should not need to type cast (int) your object variables ($data->whatever) all the time but type cast them when they're set.
Also by adding +1 to a variable PHP automatically recasts the variable as an int anyway.
Check that your $data->tooltipLastID is publicly accessible/writable.
You use $this ; so which class are you in? Are you self referencing the data class?
A bank holiday is just one day.
It is better the inserted Database column is set by the database automatically upon insert. You can use this SQL to alter your current table:
ALTER TABLE <yourTable> MODIFY COLUMN inserted timestamp DEFAULT CURRENT_TIMESTAMP
Check the type of $data->tooltipLastID? And plz use var_dump($data->tooltipLastID) and var_dump((int)$data->tooltipLastID) before the for loop to see what indeed the original value and the $x is.
Strange type casts will result in strange bugs...

php mySql Update Set is rounding decimal numbers down

I have a DB with a column called "Price"
Type is DECIMAL, Length/Values is set to 15,4 and Default is 0.0000
When running the following:
$x=1;
$table[$x]['MSRP'] = 10.5000;
$table[$x]['Materialid'] = 1744000004;
$mysql['updateprice'] = $mysql['conn']->prepare("UPDATE oc_product SET price = ? WHERE sku = ?");
$mysql['updateprice']->bind_param("ii", $table[$x]['MSRP'],$table[$x]['Materialid']); //s=string i=integer d=double b=blob
$mysql['updateprice']->execute();
The number saved comes out as "10.000"
This happens no matter which number i use.
For example,
12.7 becomes 12.0000
12.7000 becomes 12.0000
13.1 becomes 13.0000
13.1000 becomes 13.0000
When using phpmyadmin to insert the number, it works without any problems.
Ive tried using floatval and not had any luck with this.
How can I make this save exactly as given without modifying the structure of the db?
You're binding the variables as integers. You need to bind them as doubles, as you have noted in your commented code
$mysql['updateprice']->bind_param("di", $table[$x]['MSRP'],$table[$x]['Materialid']);
//s=string i=integer d=double b=blob
$mysql['updateprice']->bind_param("ii", $table[$x]['MSRP'],$table[$x]['Materialid']); //s=string i=integer d=double b=blob
try to
use bind_param("dd",...)
like as below
$mysql['updateprice']->bind_param("dd", $table[$x]['MSRP'],$table[$x]['Materialid']); //s=string i=integer d=double b=blob

Can't insert decimal value with PDO

I've been trawling the web for hours now and trying different methods, and I can't work out why PDO can't insert any row where one of the values contains a decimal.
For example, if the value entered into the cost field has no decimal value then it works fine. But anything like with a decimal and it just ignores the whole row.
200 works, even 200.00 works. But things like 39.99 don't.
Here's the code:
$invoice_id = $db->lastInsertId('id');
$item_name = $_POST['item_name'];
$item_qty = $_POST['item_qty'];
$item_cost = $_POST['item_cost'];
$item_vat = $_POST['item_vat'];
for($i = 0; $i < count($item_name); $i++) {
$item_query = $db->prepare("INSERT INTO hm_invoice_items(invoice, item, qty, amount, vat) VALUES(:invoice, :item, :qty, :amount, :vat)");
$item_query->bindParam(":invoice", $invoice_id);
$item_query->bindParam(":item", $item_name[$i]);
$item_query->bindParam(":qty", $item_qty[$i]);
$item_query->bindParam(":amount", $item_cost[$i]);
$item_query->bindParam(":vat", $item_vat[$i]);
if (!$item_query->execute())
{
die(showMessage("There has been a problem adding the invoice items.", "Error!"));
}
}
A var_dump tells me that the insert query is receiving the values, but it does not like dealing with decimals.
There could be an issue with decimal separator.
When debugging such cases it's essential to var_dump() e-ve-ry-thing!
Why don't you var_dump your values for the closer inspection?
Why didn't you play with decimals only, without POST, without other values?
A question titled "Can't insert decimal value with PDO" should contain short reproduceable code with decimal value present to readers and the result.
Judging by indirect measures will do no help for you and - especially - won't bring you help from strangers.
"var_dump your values" means every suspicious value, like
var_dump($item_cost[$i]);
inside your loop
if you get no output - then there is empty value, so, no wonder nothing inserted.
By the way, you're binding apparently decimal item_cost value to apparently integer amount field. Is it a typo?
But again - where is a certain reproduceable proofcode contains one insert query, one hardcoded decimal value and one result? Ugh - and table definition of course.
Try this?
$item_query->bindParam(":amount", floatval($item_cost[$i]));
At least it works for me when I deal with MySQL decimal data type with PDO.
Use the following to display the content of all the values POSTed to your PHP script:
print_r($_POST);

updating a large number in MySQL larger than 100 trillion with PHP is unreliable

When I send a value to MySQL in PHP like this:
$mysqli->query("update bank set cash = $cash");
It works fine for smaller numbers, but anything 100 trillion or larger yields unexpected results. Sometimes it updates the number in increments of 100, and sometimes not at all.
A prepared statement also has different, but unreliable results once the number gets larger than a couple billion:
$stmt->prepare("update bank set cash = ?");
$stmt->bind_param('i',$new_cash_amt);
$stmt->execute();
Use double quotes.
use or die(mysql_error()); to see you bug.
Stop using mysql* function, will be deprecated soon.
Fix:
$amount = 17;
$mysqli->query("
update player_stats
set cash = cash + $amount
where username = 'cheater2'
") or die(mysql_error());
You're using single quotes, which wont parse a php variable. It's looking for cash=cash+$amount as a string, not a variable holding data.
I'm answering my own question here.
It turns out that when you pass values like this:
$huge_number = 100000000000012345;
echo "The huge_number is: $huge_number";
It will print the following:
The huge_number is: 1.0000000000001E+17
The precise value is lost in this conversion. That is why the value increments in multiples of 100 sometimes, and not at all at other times.
As with the prepared statement, any values larger than a 32bit integer (since I put an 'i' as the type in the bound parameter) will get truncated and altered unexpectedly. I should have passed the new value as a 'd', like so:
$stmt->bind_param('d',$new_cash_amt); //This works correctly

PHP, PDO binding dynamic number of values into the statement

I need effective some solution for the following issue:
For some reason that would be too much time-consuming to explain properly, I need a PDO prepare statemnt sorta looking this way:
'SELECT field, another field, blabla FROM table WHERE some_foreign_id = first_val AND the_same_foreign_id = second_val AND again_the_same_id = third val ......'
and Id wish to fill the values with an array of unknown size, that depends on how many fields in that foreign table fits to a certain category in yet another table.
So the querstion is: is it even possible or should I give it up and find some naive walkaround?
Thanks in advance!
Mac
You can pass an array of values into stmt ->execute($array); The only tricky part would be getting the number of question marks to enter.
$foreign_ids = array(foreign_id_1, foreign_id_2, foreign_id_3); //etc
$input_list = substr(str_repeat(',?', count($foreign_ids)), 1); //this gets you the correct number of ? to use for your query
// if you need add another value to the parameters you can use array_push($foreign_ids,$your_other_param);
$stmt= $dbh->prepare("
SELECT field, another_field
WHERE some_foreign_id = ($input_list)");
$stmt->execute($foreign_ids);
It should be possible. You'll need to generate your query dynamically with question marks for parameters, and then bind with an array at the point of execution.
See example 3 on the PDO::execute page of the PHP docs.

Categories