MySQL datatypes for business applications? - mysql

Good day, I am confused with the datatype for MySQL.
I am using decimal as apparently it is the safest bet for accuracy in a business application. However, I find that when fields are returned I have values of 999999999.99, where my datatype is DECIMAL(10,2). So the actual value has overflowed outside the (10, 2) parameter.
Would it be correct that even though I have specified 10 places before the comma and 2 places after the comma. MySQL still stores the complete number?
Also would it be possible to turn off the maximum amount of digits displayed before and after the comma?

Would it be correct that even though I have specified 10 places before the comma and 2 places after the comma. MySQL still stores the complete number?
No, it wouldn't.
First, you specified 10 digits altogether; two are to the right of the decimal point, and eight are to the left.
Standard SQL requires that DECIMAL(5,2) be able to store any value with five digits and two decimals, so values that can be stored in the salary column range from -999.99 to 999.99.
Second, MySQL will silently convert the least significant digits to scale if there are more than two. That will probably look like MySQL truncates, but the actual behavior is platform-dependent. It will raise an error if you supply too many of the most significant digits.
Finally, when you're working with databases, the number of digits displayed has little to do with what a data type is or with what range of values it stores.

Related

Incorrect decimals appearing in SUM MySQL

I have the following SQL query.
SELECT SUM(final_insurance_total) as total
FROM `leads`
GROUP BY leads.status
I have a single row of data in the lead table with a value for final_insurance_total of 458796. The data type for final_insurance_total is float.
For some reason, MySQL is summing a single row as "458796.375".
If I change the query to
SELECT (final_insurance_total) as total
FROM `leads`
GROUP BY leads.status
the correct value is returned. What in the world is going on?
The FLOAT and DOUBLE types in MySQL (as well as in other databases and programming language runtimes) are represented in a special way, which leads to the values stored being approximations, not exact values. See MySQL docs, as well as general information on floating-point arithmetics.
In order to store and operate with exact values, use the type DECIMAL (see https://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-characteristics.html).
EDIT: I have run some tests, and while floating-point precision errors are quite common, this particular one looks to be specific to the implementation of SUM() in MySQL. In other words, it is a bug that has been there for a long time. In any case, you should use DECIMAL as your field type.
FLOAT does not guarantee precision where any calculation is made. If you use a simple SELECT, no calculation is made, so you get the original value. But if you use SUM(), even with one row, at least one addition is executed (0 + current_value).
Do you really need FLOAT? For example, if you have 2 decimal digits, you could use INT and multiply all values by 100 before all INSERTs. When SELECTing results, you will divide by 100.
If the user is not a sysadmin and cannot change the datatype of the field such as FLOAT, the user can use CAST to produce the desired output.

999.99 Value for 1138 In Mysql/PhP My Admin

I am very new to php and mysql so sorry if this is a silly question,
I am importing some measurement data into the database via PhP My Admin.
The CSV has values going from 1 to 3000, some have decimals and some don't.
Due to this I don't think the table likes the mix up.
Most of the values show correctly, apart from when the values go over 999, one of the measurement values shows 999.99 for a value of 1138.
Is there any way to stop it doing this?
Thanks for any advice!
Well, that's the problem, data type. As per the docs:
The declaration syntax for a DECIMAL column is DECIMAL(M,D). The
ranges of values for the arguments in MySQL 5.6 are as follows:
M is the maximum number of digits (the precision). It has a range of 1 to 65. (Older versions of MySQL permitted a range of 1 to 254.)
D is the number of digits to the right of the decimal point (the scale). It has a range of 0 to 30 and must be no larger than M.
So your DECIMAL(5,2) column type can hold numbers up to 999.99. You'll have to alter the table and make the column larger.
(As about why MySQL prefers to corrupt your data rather than reporting it, well, that's been its philosophy from the early years. You can play with SQL modes to fix that.)

What should be the typical length of user's Full Name in database [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
List of standard lengths for database fields
Simple as that, what should be the typical length of allowed "Full Name" of a user in database?
When I create users table, I usually set it as varchar 31 or 32 (according to performance). What do you guys use and what's standard/typical convention.
Sidenote: I never face problem in email length (as I set it 254) and password (hash, 32 length).
The maximum your average varchar field allows (254?).
You are not winning anything by making it arbitrarily shorter. The fine-grained size controls on numbers and chars are more or less a relic from the past, when every byte mattered. It can matter today - if you are dealing with tens or hundreds of millions of rows, or thousands of queries per sec. For your average database (i.e. 99% of them) performance comes from proper indexing and querying, NOT making your rows a couple of bytes smaller.
Only restrict the length of a field when there is some formal specification that defines a maximum length, like 13 digits for an EAN code or 12 characters for an ISIN.
Full name is always a computed column composed of first, middle, last, prefix, suffix, degree, family name, etc in my designs. The list of individual columns are determined by the targeted local of the app. The display length of 'Full Name' is normall contained within the app design not the database. There is not any space savings in SQL Server between varchar(32) and varchar(256). Varchar(256) is my choice.
I never want to be in the meeting when someone says "Your db design will not hold all our data".
You are always assigning an ID to the user so you can join and do look-ups using the ID instead of the FullName, correct?
I would recommend at least 128.
Well you can just put it at 255 if you want.
varchars is a Variable length storage type. This means theres 1 byte which stores the actual length of the string, varchars dont use up more bites then needed so storage wise it really does not matter. This is described on the mysql page
Description can be found here http://dev.mysql.com/doc/refman/5.0/en/char.html
It is illustrated halfway the page check the table.
VARCHAR values are not padded when
they are stored. Handling of trailing
spaces is version-dependent. As of
MySQL 5.0.3, trailing spaces are
retained when values are stored and
retrieved, in conformance with
standard SQL. Before MySQL 5.0.3,
trailing spaces are removed from
values when they are stored into a
VARCHAR column; this means that the
spaces also are absent from retrieved
values.
Conclusion:
Storage wise you could always go for 255 because it wont use up additional space and you wont get intro trouble with string getting cut off.
Greetz

MySQL 5.1.41 leading zero is deleted

I have a MySQL database where I want to store phone numbers among other things.
The fieldtype is INT(10)
When I try to insert a number starting with a 0, like 0504042858 it's stored like 504042858. This only happens with phone numbers with leading zeros. When the number start with any other number, it's stored correctly.
What am I doing wrong?
You should probably store phone numbers as a varchar. Phone numbers are only numeric by accident.
You may also be interested in checking out the following Stack Overflow posts:
What datatype should be used for storing phone numbers in SQL Server 2005?
Common MySQL fields and their appropriate data types
You can give length INT(11) with attribute value UNSIGNED_ZEROFILL. it will fill all 11 digits and if any digit length is less than 11, it will add zero itself before the value.
This might solve your problem.
it is removing the leading zero because mathematically they are the same and removing the leading zero is a quick storage optimization. In addition it also makes the numbers easier to read imagine a number padded with several leading zeros in a column of several hundred numbers.
I agree with Daniel change your column to a varchar.

Storing large prime numbers in a database

This problem struck me as a bit odd. I'm curious how you could represent a list of prime numbers in a database. I do not know of a single datatype that would be able to acuratly and consistently store a large amount of prime numbers. My concern is that when the prime numbers are starting to contain 1000s of digits, that it might be a bit difficult to reference form the database. Is there a way to represent a large set of primes in a DB? I'm quite sure that this has topic has been approached before.
One of the issues about this that makes it difficult is that prime numbers can not be broken down into factors. If they could this problem would be much easier.
If you really want to store primes as numbers and one of questions, stopping you is "prime numbers can not be broken down into factors", there are another thing: store it in list of modulus of any number ordered by sequence.
Small example:
2831781 == 2*100^3 + 83*100^2 + 17*100^1 + 81*100^0
List is:
81, 17, 83, 2
In real application is useful to split by modulus of 2^32 (32-bits integers), specially if prime numbers in processing application stored as byte arrays.
Storage in DB:
create table PRIMES
(
PRIME_ID NUMBER not null,
PART_ORDER NUMBER(20) not null,
PRIME_PART_VALUE NUMBER not null
);
alter table PRIMES
add constraint PRIMES_PK primary key (PRIME_ID, PART_ORDER) using index;
insert for example above (1647 is for example only):
insert into primes(PRIME_ID, PART_ORDER, PRIME_PART_VALUE) values (1647, 0, 81);
insert into primes(PRIME_ID, PART_ORDER, PRIME_PART_VALUE) values (1647, 1, 17);
insert into primes(PRIME_ID, PART_ORDER, PRIME_PART_VALUE) values (1647, 2, 83);
insert into primes(PRIME_ID, PART_ORDER, PRIME_PART_VALUE) values (1647, 3, 82);
prime_id value can be assigned from oracle sequence ...
create sequence seq_primes start with 1 increment by 1;
Get ID of next prime number to insert:
select seq_primes.nextval from dual;
select prime number content with specified id:
select PART_ORDER, PRIME_PART_VALUE
from primes where prime_id = 1647
order by part_order
You could store them as binary data. They won't be human readable straight from the database, but that shouldn't be a problem.
Databases (depending on which) can routinely store numbers up to 38-39 digits accurately. That gets you reasonably far.
Beyond that you won't be doing arithmetic operations on them (accurately) in databases (barring arbitrary-precision modules that may exist for your particular database). But numbers can be stored as text up to several thousand digits. Beyond that you can use CLOB type fields to store millions of digits.
Also, it's worth nothing that if you're storing sequences of prime numbers and your interest is in space-compression of that sequence you could start by storing the difference between one number and the next rather than the whole number.
This is a bit inefficient, but you could store them as strings.
If you are not going to use database-side calculations with these numbers, just store them as bit sequences of their binary representation (BLOB, VARBINARY etc.)
Here's my 2 cents worth. If you want to store them as numbers in a database then you'll be constrained by the maximum size of integer that your database can handle. You'd probably want a 2 column table, with the prime number in one column and it's sequence number in the other. Then you'd want some indexes to make finding the stored values quick.
But you don't really want to do that do you, you want to store humongous (sp?) primes way beyond any integer datatype you've even though of yet. And you say that you are averse to strings so it's binary data for you. (It would be for me too.) Yes, you could store them in a BLOB in a database but what sort of facilities will the DBMS offer you for finding the n-th prime or checking the primeness of a candidate integer ?
How to design a suitable file structure ? This is the best I could come up with after about 5 minutes thinking:
Set a counter to 2.
Write the two-bits which represent the first prime number.
Write them again, to mark the end of the section containing the 2-bit primes.
Set the counter to counter+1
Write the 3-bit primes in order. ( I think there are two: 5 and 7)
Write the last of the 3-bit primes again to mark the end of the section containing the 3-bit primes.
Go back to 4 and carry on mutatis mutandis.
The point about writing the last n-bit prime twice is to provide you with a means to identify the end of the part of the file with n-bit primes in it when you come to read the file.
As you write the file, you'll probably also want to make note of the offsets into the files at various points, perhaps the start of each section containing n-bit primes.
I think this would work, and it would handle primes up to 2^(the largest unsigned integer you can represent). I guess it would be easy enough to find code for translating a 325467-bit (say) value into a big integer.
Sure, you could store this file as a BLOB but I'm not sure why you'd bother.
It all depends on what kinds of operations you want to do with the numbers. If just store and lookup, then just use strings and use a check constraint / domain datatype to enforce that they are numbers. If you want more control, then PostgreSQL will let you define custom datatypes and functions. You can for instance interface with the GMP library to have correct ordering and arithmetic for arbitrary precision integers. Using such a library will even let you implement a check constraint that uses the probabilistic primality test to check if the numbers really are prime.
The real question is actually whether a relational database is the correct tool for the job.
I think you're best off using a BLOB. How the data is stored in your BLOB depends on your intended use of the numbers. If you want to use them in calculations I think you'll need to create a class or type to store the values as some variety of ordered binary value and allow them to be treated as numbers, etc. If you just need to display them then storing them as a sequence of characters would be sufficient, and would eliminate the need to convert your calculatable values to something displayable, which can be very time consuming for large values.
Share and enjoy.
Probably not brilliant, but what if you stored them in some recursive data structure. You could store it as an int, it's exponent, and a reference to the lower bit numbers.
Like the string idea, it probably wouldn't be very good for memory considerations. And query time would be increased due to the recursive nature of the query.