mySQL: I need to input a decimal into an int column - php

I have a table with a current structure as follows:
Currently this is populated as follows:
The data stored for product value is a decimal value
and the end digits are cut off once it is inserted into the database.
I have tried changing the table structure as follows:
However this only leads to the following:
As you can see all values have a .00 appended if none exists, however I want to
store all these values with no decimal places. Except the product value.
How can I do this?

The trouble is you are converting a decimal (float / double) to an integer, so the value is simply truncated (decimal values are chopped off).
If you really don't want to use floats (decimal values) in the database you can use this hack work around will work:
Multiply the number by 100 before inserting it, and then be sure to divide it by 100 when you use the data. This will allow you to maintain 2 decimal points while using integer storage.
Thus, 2.4 would be stored as 240, 53 would be 5300, 20.74 becomes 2074 etc...
I want to note that this is not an ideal solution, but rather a hack.
I highly recommend what the other users suggested in the comments: storing the decimal value (as you have) and formatting it when presenting it.
--- In addition ---
Your real problem appears to be with the way the database is setup.
Each of those values should have their own field since they will be repeated for each product.

Related

How to correctly insert decimals to MySQL database

I would like to know the proper way to insert decimals to a MySQL database
When I use the type decimal and if I enter 0.20 to the database its saving the value as 0
And when I use the type float and if I enter 0.20 to the database its saving the value as 0.2
I want to display the same value that enter and also, I want to use this value for filters. So, I don’t want to use the varchar type to inset these values.
Can someone tell me what is the best way to do this? I wouldn't mind using PHP to display the missing end zero.
Appreciate your time.
10,0 means 10 characters 0 of which are decimal. 10,2 would mean 8 numbers to the left, 2 to the right of the decimal.
Float should only be used when you are dealing with extremely large or small numbers; like the number of atoms in the galaxy where precision does not matter but scale does.
Lastly don't mix the concepts of "Display"(format) and value. Display is a formatting matter. The value 0005.50000 is the same as 5.5. Their display is just a matter of formating.

While inserting long integer values in mysql database in it always round up number

I have tried to insert integer like 356361070084127 in mysql table named IMEI. However, while inserting it from excel file it convert these IMEI automatically to 356361070084120 changing last digit to 0. I have used PHPExccel to upload the excel file.
SUGGESTIONS:
Do a "select" in mysql to verify the "bigint" shows as expected in the database.
In "Excel":
a) select one of the integer values
b) Navigate to Home > Number
c) Increase Decimal
I suspect the actual problem is that Excel might be converting the integer to floating point, then rounding the floating point value.
One way to prevent this is to store the value as a "string" instead of "integer" - that way you can store a decimal value that's arbitrarily long.
Here is some additional information:
https://www.cnet.com/forums/discussions/displaying-long-numbers-greater-than-15-char-in-excel-292538/
ADDENDUM:
If you want to store an IMEI number ... THEN USE TYPE "STRING"! In the database, and ESPECIALLY in Excel!

PostgreSQL real type losing integer precision when printed with PHP sprintf

I have copied this table from Wikipedia into a PostgreSQL database. The column Cultivated land (km2) became a column of type real. Then I use the PHP command
echo rtrim(rtrim(sprintf('%.10F',$v),'0'),'.');
to display the numbers ($v) in a table (both integers and float), but some values lose precision. For instance, the value from United States, 1669302, becomes 1669300, what is strange, since I expected 10 decimal digits of precision. I thought I have lost the precision when saving into a real column, but converting the column to double precision makes the difference (02) appear again, so it was there somewhere.
I don't think I need double precision, so how can I display the real value correctly? Keep in mind that some columns have decimal places, while some others are bigint, and they also should be displayed correctly.
The problem seems to originate from the way PHP returns results. The values are not returned as the corresponding data type, but rather formatted as a string using PostgreSQL default formatting. This formatting, is different for real and double precision types hence you are seeing different results when you convert the column types of your table. The reason you are seeing this specific result is that PostgreSQL guarantees 6 decimal places for real types and 15 decimal places for double precision.
Setting extra_float_digits
The manual states
Note: The extra_float_digits setting controls the number of extra significant digits included when a floating point value is converted to text for output. With the default value of 0, the output is the same on every platform supported by PostgreSQL. Increasing it will produce output that more accurately represents the stored value, but may be unportable.
Therefore, a simple solution to your problem is to increase extra_float_digits before issuing your SELECT-query:
pg_query($connection, "set extra_float_digits = 3");
Alternatively, you can also specify this change when connecting to your database by adding options to your connection string as follows:
$connection = pg_connect("host=localhost port=5432 dbname=test user=php password=pass connect_timeout=5 options='-c extra_float_digits=3'");
Another option would be to set this flag in the postgresql.conf configuration file of the PostgreSQL server if you have access to the server and want to change the option globally.
Casting the values
A different solution would be to have PostgreSQL return a different string to the PHP backend. This can be achieved by casting your columns to types with different default formatting which avoids cutting off some of the digits. In your case you could either cast to integer or double precision, i.e. instead of using
select cultivated_land from table
you could use
select cultivated_land::integer from table
or
select cultivated_land::double precision from table
Changing data types
Looking at the data you specified, I noticed that all numerical values except those columns specifying percentages contain integers, hence the usage of the integer data type is more suitable in this case. It can fit all the integer values of this table (the maximum being 149,000,000, therefore bigint is not required), requires the same storage size as real (4 bytes) and implies the default formatting of integers that you are looking for.
Update: Background on PostgreSQL-PHP interface and floating point representation
As mentioned above the way the PostgreSQL-PHP interface works is that all values sent from PostgreSQL to PHP are formatted as a string in some type-dependent way. Neither any of the pg_fetch_* functions nor pg_copy_to will provide raw values and all of these functions convert the values to strings in the same manner. As far as I am aware the current PHP interface will not provide you with anything different from a string (which, in my opinion, is not the best interface design).
The reason 18.22 is returned as 18.2199993 can be found in how PostgreSQL converts float4 to strings. You can check the code of how PostgreSQL is internally using float4out and find this relevant line that does the string-conversion:
snprintf(ascii, MAXFLOATWIDTH + 1, "%.*g", ndig, num);
num is the float4-number to be printed as a string. Note however that C will promote the float-variable to a double-variable when calling snprintf. This conversion to double precision results in the value 18.219999313354492 which is why you end up seeing 18.2199993 (you can check this here and will also find some details on floating point number representation on this site).
The takeaway message is that all your float4 values will be converted using this function and the only parameter you can influence is ndig by varying extra_float_digits, however no single value for this variable will suffice all your needs in representing the values as you want them. So as long as you keep using float4 as your data type and use the current PHP-interface to obtain the data you will run into these problems.
I therefore still recommend choosing different data types for your columns. If you think you have a requirement for decimal numbers you might want to investigate decimal data types where you can specify precision and scale as required for your application. If you would like to stick with floating point numbers I suggest rounding the values in PHP before displaying them to the user.

Data type in php for both decimal and character values

Data type in php (that I should set for a column in phpmyadmin) for entering both character and decimal numbers. Ex. 0.09 or n.a. or 100 (1) all such things can be feed in to the column.
A VARCHAR type can be used. This will store a string allowing your characters or decimals. Be sure to set an appropriate length - not too short or the data will be truncated.
If you find yourself storing lots of different types of data in a single field, then it may suggest you could use a better table/db design.
I would personally store that data in two different fields:
one INT for whole numbers
and one DEC(m,n) for decimal numbers * m is number of all digits and n is number of digits behind the decimal separator.
For example: DEC(5,2) data for this would be 123.45
If you need it to be in one field use VARCHAR but this is not my recommend, since it is not good to store integers in varchar type field.
Though a varchar is not recommended, but if you are using a varchar make sure you typecast the variable in your code while fetching.

MySQL greater than with microtime timestamp

I have one PHP script inserting rows in a MySQL database. Each row has a field 'created_at' which is filled with the value of the PHP function microtime(true), and inserted as a double. (microtime because I need something more precise than to the second)
I have another PHP script that selects rows based on that created_at field.
When I go ahead and select like this:
SELECT * FROM `ms_voltage` WHERE created_at > 1302775523.51878
I receive a resultset with, as the first row, the row with exactly that value for created_at.
This occurs from within my PHP script and from within PhpMyAdmin when manually doing the query. But not always, not for every value. Just once and a while really.
How is this possible? I didn't ask for greater than/equals, I want strictly greater than.
Am I overlooking something type-related perhaps?
Yeah, floating point arithmetic can do that sometimes. To understand why, it's helpful to realize that just as not all numbers can be accurately represented in base 10, not all numbers can be accurately represented in base 2 either.
For example, "1/3" may be written in base 10 as 0.33333 or 0.33334. Neither is really "correct"; they're just the best we can do. A "DOUBLE" in base 10 might be 0.3333333333 or 0.3333333334, which is double the digits, yet still not "correct".
The best options are to either use a DECIMAL value, or use an INT value (and multiply your actual values by, say, 10000 or 100000 in order to get the decimal digits you care about into that int).
The DOUBLE type represent only approximate numeric data values. Try to use the DECIMAL type.
Is your column floating point? Calling microtime with true gives you a float, and that looks like a float, which will have digits after the .51878 that you don't see, so those digits make the stored value greater than the value you have in your query.
Unless you really need the float I'd convert the string result to an int, or even two columns for seconds and useconds. Then you can use > or < on known values without worrying about the imprecision of the floating point value.

Categories