How to update exact decimal value in mysql database - mysql

I am working with mysql. I created a column in database called "balance" and the datatype for this column is "DECIMAL(12,6)".
So whenever I try to update 4 digits after the decimal point then the last two digits are showing random values (e.g. balance is showing 4444.888672 for the following query).
Here is my current query
UPDATE `table` SET `balance` = '4444.8888' WHERE `token_address` = 'abc123'

Sounds like common float overflow issue, where decimal part does not fit into memory and is cut off.
In our system we use INT's instead. So you would save into database 44448888000 and in PHP you would parse it as $row['balance'] / 1000000

Related

How to select one column value, normalize and put to another column in mysql?

In my table, I've got a column call mobile and I need this mobile field value to be normalized and save to another column call formatted_phone. For this purpose, I am using the below MySQL query and unfortunately, it is not working. I am putting my query here, please someone correct it. Thank you.
UPDATE hiring_detail
SET formatted_phone = replace(replace(
replace(replace(replace(replace(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.','')
WHERE mobile IS NOT NULL;
Error what it throws:
SQL Error (1265):Data truncated for column 'formatted_phone' at row 3
mobile column: varchar 50
formatted_phone: bigint 15
Usually, beofre blindly executing UPDATE commands, we do a simply What If analysis first, just run the query as a SELECT so you can inspect the output and importantly, you can compare it to the existing values:
http://sqlfiddle.com/#!9/47723a/2
SELECT mobile, formatted_phone
, REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.','') as test
FROM hiring_detail
WHERE mobile IS NOT NULL;
If that logic works for you (and it does in my tests) then there should be no issue with your UPDATE logic.
UPDATE:
If your error is
SQL Error (1265):Data truncated for column 'formatted_phone' at row 3
Then that means that your formatted phone numbers are longer than the column width for formatted_phone. If you know what the length is, you can truncate your formatted numbers, but with phone numbers, if we remove the actual number, this usually results in phone numbers that cannot be called.
I would recommend instead that you increase the width of the formatted_phone field.
This is an example of a forced truncation:
UPDATE hiring_detail
SET formatted_phone = RIGHT(replace(replace(
replace(replace(replace(replace(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.',''),10)
WHERE mobile IS NOT NULL;
Update #2
given that the column is an int, we need to convert the value into an integer.
UPDATE hiring_detail
SET formatted_phone = CAST(replace(replace(
replace(replace(replace(replace(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.','') as UNSIGNED INT)
WHERE mobile IS NOT NULL;
Warning: It is NOT advisable to store phone numbers as integers, the leading zeros can be significant in area codes in many localities, by storing as a numeric value this can have significant effects and can result in los of data. It also makes it hard to search for partial matches on the numbers. Almost all operations that you can think of (including sorting) on phone numbers will involve string manipulations, not mathematical or numerical.

Getting the wrong answer when getting the sum of column name

I have a problem in getting the sum of one of my column names in database (PRICE). If I insert 1000.00 and 3600.00 to get the sum of them, I am getting 4.00 instead of 4600.00. But when the total is below 1000 I get the correct answer.
It appears that your price_per_case column is char or varchar column rather than a numeric column such as decimal(10,2). So, it is converting the column to double but ignoring everything after the , character (and probably issuing warnings during the conversion). You can verify this by trying the following:
select '1,234' + '3,456';
You will end up with 4;
You should try running:
update ordered set price_per_case = replace(price_per_case, ',', ''); /* get rid of commas */
Then you should change the type of this column to decimal(10,2) or some appropriate precision.
Maybe the machine when you are programming have different “Locale” of MySql Server (are both in the same machine)?
In this case also format currency/double/decimal is different.
To avoid that you need to change Locale in you .NET method/sub/function before/into you get query result
Threading.Thread.CurrentThread.CurrentCulture = New CultureInfo("it-IT")
Threading.Thread.CurrentThread.CurrentUICulture = New CultureInfo("it-IT")
or change Locale in MySql
SET lc_time_names = 'it_IT'; Here continue your query
In this example I have used Italian Locale

Changing over from double data type to decimal

I have a database that currently uses the double data type and I want to change it to using the deciaml data type as I heard the double data type can't really be trusted when storing monetary data as it's approximate.
So I'm just wondering if I should expect any issues if I just change the data type? Everything should change ok with no loss of data?
Yes, you do have a risk of losing data unless planned carefully, but as long as you ensure that your data is already consistent and you choose correct length for the field you should be fine. Consider the following:
ALTER TABLE yourtable MODIFY COLUMN yourcolumn DECIMAL;
This will convert yourcolumn into DECIMAL but it'll result in DECIMAL(10,0) which is practically integer column. If you go ahead and convert to DECIMAL(10,2) instead:
ALTER TABLE yourtable MODIFY COLUMN yourcolumn DECIMAL(10,2);
You will lose everything beyond 2nd decimal. As an example value 10.025 will be converted to 10.03. If all your values already have only two decimal positions you should be fine.
All above holds for MySQL 5.5.25
One safe way to do is as
alter table your_table add column `test_col` decimal(8,2);
Then copy the existing values to the new col as
update table `your_table` set test_col = `col_double_datatype`;
Then check if the data is copied properly and if looks good drop the col_double_datatype and rename the test_col to the one you are using.
None of the above solutions worked for me on MySQL 8.
My solution (with a decimal(14, 4) field):
UPDATE your_table SET test_col = cast((col_double_datatype * 1000000 / 1000000) as decimal(14, 4));

"Data too long for column" - why?

I've written a MySQL script to create a database for hypothetical hospital records and populate it with data. One of the tables, Department, has a column named Description, which is declared as type varchar(200). When executing the INSERT command for Description I get an error:
error 1406: Data too long for column 'Description' at row 1.
All the strings I'm inserting are less than 150 characters.
Here's the declaration:
CREATE TABLE Department(
...
Description varchar(200)
...);
And here's the insertion command:
INSERT INTO Department VALUES
(..., 'There is some text here',...), (..., 'There is some more text over here',...);
By all appearances, this should be working. Anyone have some insight?
Change column type to LONGTEXT
I had a similar problem when migrating an old database to a new version.
Switch the MySQL mode to not use STRICT.
SET ##global.sql_mode= 'NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
Error Code: 1406. Data too long for column - MySQL
There is an hard limit on how much data can be stored in a single row of a mysql table, regardless of the number of columns or the individual column length.
As stated in the OFFICIAL DOCUMENTATION
The maximum row size constrains the number (and possibly size) of columns because the total length of all columns cannot exceed this size. For example, utf8 characters require up to three bytes per character, so for a CHAR(255) CHARACTER SET utf8 column, the server must allocate 255 × 3 = 765 bytes per value. Consequently, a table cannot contain more than 65,535 / 765 = 85 such columns.
Storage for variable-length columns includes length bytes, which are assessed against the row size. For example, a VARCHAR(255) CHARACTER SET utf8 column takes two bytes to store the length of the value, so each value can take up to 767 bytes.
Here you can find INNODB TABLES LIMITATIONS
in mysql if you take VARCHAR then change it to TEXT bcoz its size is 65,535
and if you can already take TEXT the change it with LONGTEXT only if u need more then 65,535.
total size of LONGTEXT is 4,294,967,295 characters
Varchar has its own limits. Maybe try changing datatype to text.!
Turns out, as is often the case, it was a stupid error on my part. The way I was testing this, I wasn't rebuilding the Department table after changing the data type from varchar(50) to varchar(200); I was just re-running the insert command, still with the column as varchar(50).
If your source data is larger than your target field and you just want to cut off any extra characters, but you don't want to turn off strict mode or change the target field's size, then just cut the data down to the size you need with LEFT(field_name,size).
INSERT INTO Department VALUES
(..., LEFT('There is some text here',30),...), (..., LEFT('There is some more text over here',30),...);
I used "30" as an example of your target field's size.
In some of my code, it's easy to get the target field's size and do this. But if your code makes that hard, then go with one of the other answers.
For me, I defined column type as BIT (e.g. "boolean")
When I tried to set column value "1" via UI (Workbench), I was getting a "Data too long for column" error.
Turns out that there is a special syntax for setting BIT values, which is:
b'1'
With Hibernate you can create your own UserType. So thats what I did for this issue. Something as simple as this:
public class BytesType implements org.hibernate.usertype.UserType {
private final int[] SQL_TYPES = new int[] { java.sql.Types.VARBINARY };
//...
}
There of course is more to implement from extending your own UserType but I just wanted to throw that out there for anyone looking for other methods.
Very old question, but I tried everything suggested above and still could not get it resolved.
Turns out that, I had after insert/update trigger for the main table which tracked the changes by inserting the record in history table having similar structure. I increased the size in the main table column but forgot to change the size of history table column and that created the problem.
I did similar changes in the other table and error is gone.
I try to create a table with a field as 200 characters and I've added two rows with early 160 characters and it's OK. Are you sure your rows are less than 200 characters?
Show SqlFiddle
There was a similar problem when storing a hashed password into a table. Changing the maximum column length didn't help. Everything turned out to be simple. It was necessary to delete the previously created table from the database, and then test the code with new values ​​of the allowable length.
If you re using type: DataTypes.STRING, then just pass how long this string can be like DataTypes.STRING(1000)
In my case this error occurred due to entering data a wrong type for example: if it is a long type column, i tried to enter in string type. so please check your data that you are entering and type are same or not
For me, I try to update column type "boolean" value
When I tried to set column value 1 MySQL Workbench, I was getting a "Data too long for column" error.
So for that there is a special syntax for setting boolean values, which is:
UPDATE `DBNAME`.`TABLE_NAME` SET `FIELD_NAME` = false WHERE (`ID` = 'ID_VALUE'); //false for 0
UPDATE `DBNAME`.`TABLE_NAME` SET `FIELD_NAME` = true WHERE (`ID` = 'ID_VALUE'); //true for 1
I had a different problem which gave the same error so I'll make a quick recap as this seems to have quite different sources and the error does not help much to track down the root cause.
Common sources for INSERT / UPDATE
Size of value in row
This is exactly what the error is complaining about. Maybe it's just that.
You can:
increase the column size: for long strings you can try to use TEXT, MEDIUMTEXT or LONGTEXT
trim the value that is too long: you can use tools from the language you're using to build the query or directly in SQL with LEFT(value,size) or RIGHT(...) or SUBSTRING(...)
Beware that there is a maximum row size in a MySQL table as reported by this answer. Check documentation and InnoDB engine limitations.
Datatype Mismatch
One or more rows are of the wrong datatype.
common sources of error are
ENUM
BIT: don't use 1 but b'1'
Data outlier
In a long list of insert one can easily miss a row which has a field not adhering to the column typing, like an ENUM generated from a string.
Python Django
Check if you have sample_history enabled, after a change in a column size it must be updated too.

mysql decimal rounding

I am inserting decimals into my MYSQL database but the values that end up in the DB are rounded, despite my having set the DB to DECIMAL(10,4). For example I set the discount to 6.5 and the DB records it as 7.
My query is:
$save = sprintf("
INSERT INTO discount
SET am_discount = %d,
tx_discount = '%s'
",
$_POST['am_discount'],
mysql_escape_string($_POST['tx_discount'])
);
I've tried setting the am_discount field to %u and %f as well, but it doesn't seem to make a difference.
As I mentioned, the am_discount field in my MYSQL DB is set to DECIMAL (10,4) and I've also tried (10,2) and (8,2).
What am I missing?
Try :
$save = sprintf("INSERT INTO discount SET am_discount = '".$_POST['am_discount']."',
tx_discount = '".mysql_escape_string($_POST['tx_discount'])."' ");
its seem to be database table column property issue, if some one can endorse me on it.
please change your table column property to "Float".
MySQL permits a nonstandard syntax: FLOAT(M,D) or REAL(M,D) or DOUBLE PRECISION(M,D). Here, “(M,D)” means than values can be stored with up to M digits in total, of which D digits may be after the decimal point. For example, a column defined as FLOAT(7,4) will look like -999.9999 when displayed. MySQL performs rounding when storing values, so if you insert 999.00009 into a FLOAT(7,4) column, the approximate result is 999.0001.
Reference :
http://dev.mysql.com/doc/refman/5.0/en/floating-point-types.html
It is not a database table column property issue. Decimal is the correct column type.
For inserts into a DECIMAL or integer column, the target is an exact data type, so rounding uses “round half away from zero,” regardless of whether the value to be inserted is exact or approximate.
See http://dev.mysql.com/doc/refman/5.0/en/precision-math-rounding.html for details.
This has nothing to do with the database, actually. It's sprintf behavior for %d.
%d The argument is treated as an integer and presented as a (signed) decimal number.