php mySql Update Set is rounding decimal numbers down - php

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

Related

PHP: strings automatically converted to float and gives negative numbers

I have a PHP code that will compute the balance of the quantity but it gives me a negative value as a balance quantity as shown in the image below.
I tried to check the quantities if what's causing the problem and try to var_dump the quantity. after checking using var_dump, it shows that the data type of my quantity is string while my balance quantity is float.
so far, I have my code below:
$query_po_quantity = mysqli_query($new_conn, "SELECT quantity, po_number FROM purchase_order WHERE supplier_name = '$supplier_name' AND category_name = '$category_name' AND activity = '$activity' AND description = '$description'");
$row = mysqli_fetch_assoc($query_po_quantity);
$po_quantity = $row['quantity'];
$po_number = $row['po_number'];
$query_rr_quantity = mysqli_query($new_conn, "SELECT SUM(total_received) AS quantity FROM receiving_reports WHERE po_number = '$po_number' AND category_name = '$category_name' AND activity = '$activity' AND description = '$description'");
$row = mysqli_fetch_assoc($query_rr_quantity);
$rr_quantity = $row['quantity'];
$balance = $po_quantity - $rr_quantity;
$supplier_name = preg_replace('/\\\\/', '', $supplier_name);
echo $po_quantity.' - '.$rr_quantity.' = '.$balance.'<br />';
This is the output:
how can I get the actual balance?
The reason you're getting an incorrect result when calculating 0.42 - 0.420000000000000000004 is due to errors with floating point precision. This is due to the way floating point numbers are stored, and both MySQL and PHP are susceptible to floating point errors if done incorrectly, but they also both have ways to prevent them when you do need highly precise calculations. With floating point types only the approximate value is stored and attempts to treat them as exact values in comparisons may lead to problems.
For PHP, this means you need to use either the arbitrary precision math functions or gmp functions. For MySQL, you need to be storing the numbers using the DECIMAL format with the desired precision you require.
First thing's first, you need to change the data type of your column in MySQL to DECIMAL, not a string. Strings are inappropriate to store numbers. Even if you were using a FLOAT or DOUBLE to store your values
your code may have actually worked, because these values likely would have been rounded.
Next, seeing as the value 0.420000000000000000004 came from a string stored in your database, I'm assuming the error stems from whatever calculations you did using PHP beforehand when you were calculating the value to be inserted. You will need to update this code to use precise math.
Use number_format:
$rr_quantity = number_format($row['quantity'], 2);
Float variable range 1.7E-308 and 1.7E+308 so it's give 15 digits of accuracy. Use number format

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

float not working in mysql database

i am using $_GET['var'] to get a variable then compare it with a variable in my database. the variable is 1.1 the var is set to "float" on the database so i know it can handle decimals but when i compare them with the code below i get nothing.
include 'connect.php';
$sql=mysql_query("SELECT * FROM table WHERE stuff='$stuff'");
while ($row=mysql_fetch_assoc($sql)) {
$start=$row['start'];
}
echo $start; //nothing happens
From what I know float type isn't precise. It doesn't show you that actual value so 1.1 that you saved may not be the actual value stored. Trying setting your field as decimal and give it a length of say, 10,1 where 10 is the maximum number of digits (the precision) and 1 is the number of digits to the right of the decimal point (the scale). It should work doing query like stuff='1.1' or stuff=1.1.
WHERE stuff = '$stuff' is a String comparison.
Compare number like so
WHERE stuff = $stuff
Don't use float( even if you insert 1.1 into the table, the actual value for float type is not 1.1, but something like 1.100000023841858) . Change it to double in database (or decimal)
You might not be seeing any output because your echo is outside the loop.
The scope of your variable $start would be confined to the loop.
Change the stuff field to DOUBLE type.
Then,
SELECT * FROM table WHERE stuff=$stuff
this should be the sql query

MySQL SELECT Statement not working when executed from PHP

I have the following piece of code, executing a pretty simple MySQL query:
$netnestquery = 'SELECT (`nested`+1) AS `nest` FROM `ipspace6` WHERE `id`<='.$adaddr.' AND `subnet`<='.$postmask.' AND `type`="net" AND `addr` NOT IN(SELECT `id` FROM `ipspace6` WHERE `addr`<'.$adaddr.' AND `type`="broadcast") ORDER BY `id`,`subnet` DESC LIMIT 1';
$netnestresults = mysql_query($netnestquery);
$netnestrow = mysql_fetch_array($netnestresults);
$nestlvl = $netnestrow['nest'];
echo '<br> NESTQ: '.$netnestquery;
Now, when I execute this in PHP, I get no results; an empty query. However, when I copy and paste the query echoed by my code (for debug purposes) into the mysql command line, I get a valid result:
mysql> SELECT (`nested` + 1) AS `nest` FROM `ipspace6` WHERE `id`<=50552019054038629283648959286463168512 AND `subnet`<=36 AND `type`='net' AND `addr` NOT IN (SELECT `id` FROM `ipspace6` WHERE `addr`<50552019054038629283648959286463168512 AND `type`='broadcast') ORDER BY `id`,`subnet` DESC LIMIT 1;
+------+
| nest |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
Can anybody tell me what I'm doing wrong? I can't put quotes around my variables, as then MySQL will try to evaluate the variable as a string, when it is, in fact, a very large decimal. I think I might just be making a stupid mistake somewhere, but I can't tell where.
Can you modify the line to say $netnestresults = mysql_query($netnestquery) or die(mysql_error());
It may be giving you an unknown error, such as a bad connection, missing DB, etc.
do an echo $netnestquery
before calling mysql_query
also add a die(mysql_error()) there.
WHERE `id`<=50552019054038629283648959286463168512
That's a pretty big number there.
PHP has issues with big numbers. The maximum size of an integer depends on how PHP was compiled, and if it's on a 64-bit system.
Have you checked that the variable containing that number hasn't been capped to a 32-bit or 64-bit integer? If it has been capped, you're going to need to take steps to make sure it's only being stored as a string in PHP. MySQL accepts strings that are entirely numeric as numbers without complaining.
(That being said, I'm not sure that MySQL can do anything with a number larger than 64-bits. The largest integer column is BIGINT, which is 64-bits. There's also NUMERIC, but it's treated as a floating point number, and that might not be what you want to do...)

Categories