MySQL Workbench out of range value for decimal number - mysql

I wanted to create an table
create table Oceny_projekty
(
OProj_Id int not null comment '',
ID_Projektu int comment '',
ID_Studenta int comment '',
OProj_Ocena decimal(1,1) comment '',
OProj_Data date comment '',
primary key (OProj_Id)
);
And fill it with sample data generated by PowerDesigner
insert into Oceny_projekty (OProj_Id, ID_Projektu, ID_Studenta, OProj_Ocena, OProj_Data)
values (2, 18, 10, '2.5', '1857-12-25');
And I've got this:
insert into Oceny_projekty (OProj_Id, ID_Projektu, ID_Studenta,
OProj_Ocena, OProj_Data) values (2, 18, 10, '2.5', '1857-12-25') Error
Code: 1264. Out of range value for column 'OProj_Ocena' at row 1
How can I modify command that can accept decimal numbers? (with integer numbers there is no problem)
Using MySQL Workbench 6.3, PowerDesigner 16.6
Thanks in advance!

Declaring OProj_Ocena as decimal(1,1) means that it has 0 integer digits (precision - scale = 1 - 1 = 0) and 1 fractional digit. It can only store values 0, 0.1, 0.2 ... 0.9.
The datatype you need is probably decimal(2,1).

Putting Marek Grzenkowicz's answer in another way, DECIMAL(M, D):
M = D + (the number of whole number digits). See 12.25.2 DECIMAL Data Type Characteristics
So, determine the number of whole number digits you want, those to the left of the decimal point, and the number of decimal places (D) that you need and add them to get M. IMO, they should have used the phrase "whole number digits" or "integer digits" to make this a bit more obvious even though what they say means that as M is for ALL digits. I misinterpreted this at first until I reread their description a few times.

Related

mysql expression for random uuid4?

Mysql offers a UUID() function,
which returns an rfc 4122 version 1 guid.
This is an easily guessed timestamp + node_id bit string.
How may we insert randomized version 4 guids?
(Defining a new function requires permissions and is out-of-scope.
Ben Johnson offers an expression that is very nice but a little verbose.)
This inserts a version-4 random string, without dashes.
In the interest of conciseness it uses a slightly reduced portion of the key space,
just 120 bits.
(So 8-bits are predictable, they're constant.)
-- Produces version 4 guids for mysql, as its UUID() only offers version 1.
--
-- See https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
-- We consider variant 1 only, ignoring the Microsoft proprietary variant 2.
-- Version 1 is predictable timestamp.
-- Version 4 is 122 random bits + 6 constant bits.
--
-- The nil guid comes out like this:
-- UUID('00000000-0000-4000-8000-000000000000') # 8-4-4-4-12
-- The nybble '4' is constant version.
-- The nybble '8' has hi bit set, next bit cleared, plus two wasted bits.
-- We deliberately choose to emit just 120 random bits, for simplicity.
-- The RAND() function returns about 53 bits of entropy in the mantissa,
-- so for 15 nybbles we call it twice to obtain 106 ( > 60 ) unguessable bits.
-- The standard spelling of a guid, with four '-' dashes, is 36 characters.
-- We emit 32 hex characters, sans dashes.
INSERT INTO guid_test (guid) VALUES (
concat(substr(sha2(rand(), 256), 1, 12),
'4', substr(sha2(rand(), 256), 1, 3),
'8', substr(sha2(concat(rand(), rand()), 256), 1, 15)
)
);

Integers and decimals to varchar sql-server

I have a set of numbers 1-55. Including three decimals between each (x.1, x.2 and x.3) where the value of the number is not important, yet the string of characters is. (i.e. 1, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 2.3, 3,...55). I am having trouble with keeping the format of the whole numbers to just the whole number character (i.e. 1,2,3,4... instead of 1.0, 2.0, 3.0, 4.0). These are two completely different things.
I’m pretty sure I need to be able to store this set as a char/varchar/text but it’s difficult when I can’t figure out how to get them all stored as character strings.
Any help would be appreciated!
Thanks!
Edit: May be pertinent and I apologize because I I figured my question at face value was complete. It was not. There will be at least 30 columns that contain frequencies associated with each of these numbers. The numbers (1-55 with the decimals between as listed above) will be used in a comparison process to return the frequency (ie get me the frequency that matches 22.3, or 30). In some instances the values being compared to my table will have letters and symbols, thus I figured that I would need these stored as characters rather than numbers. Explicitly, 1, 1.1, 1.2, 1.3, 2, 2.1, 2.2 etc up to 55 as a varchar(4) rather than a decimal(3,1) because a decimal (3,1) can’t be compared to a varchar(4)...can it?
The problem I am having is that when I add values 1, 2, 3 as varchar (4) data types to the table and query it, sql returns 1, 2, 3 but when I also add 1.1, 1.2 and 1.3 then query it, my numbers 1, 2, 3 return as 1.0, 2.0 and 3.0. I guess maybe the better question would be, is a 1 as a varchar data type the same as a 1.0 varchar datatype? I was thinking no. How can I force the character 1 to remain 1 and not change to 1.0 when I add other data to the table that has .1, .2 or .3 after it?
your question is confusing, however, please check code below with some comments if it helps you achieve what you want.
-- Populate numbers as varchar(4)
DECLARE #Numbers TABLE (Number varchar(4));
DECLARE #Number INT
SET #Number = 1
WHILE #Number <= 55
BEGIN
INSERT INTO #Numbers VALUES(#Number);
INSERT INTO #Numbers VALUES(#Number + 0.1);
INSERT INTO #Numbers VALUES(#Number + 0.2);
INSERT INTO #Numbers VALUES(#Number + 0.3);
SELECT #Number = #Number + 1
END
SELECT Number FROM #Numbers
--You can compare decimal value with table
DECLARE #DecimalNumber AS decimal(3,1)
SET #DecimalNumber=22.3
SELECT Number FROM #Numbers WHERE Number=#DecimalNumber
SET #DecimalNumber=30
SELECT Number FROM #Numbers WHERE Number=#DecimalNumber
--You can also compare varchar value with table
DECLARE #VarcharNumber varchar(4)
SET #VarcharNumber='40'
SELECT Number FROM #Numbers WHERE Number=#VarcharNumber
Let me know if you can clarify further and/or provide sample code/data.

mySQL column without a one-size-fits-all precision for DECIMAL

When I define a table to store decimal values I use a statement like this:
CREATE TABLE myTable (
myKey INT NOT NULL,
myValue DECIMAL(10,2) NOT NULL,
PRIMARY KEY (myKey)
);
However, this results in every myValue being stored with a one-size-fits-all precision of (10,2). For instance
45.6 becomes 45.60
21 becomes 21.00
17.008 becomes 17.01
But what if each record has a myValue of different precision? I need 45.6 to remain 45.6, 21 to remain 21, and 17.008 to remain 17.008. Otherwise the precision of measurement is being lost. There's a big difference between 21 and 21.00.
If you don't need to do greater/less-than compares, store as a VARCHAR(..)
The strings '21' and '21.00' would have identical values, but present different "precision".
When needing the numeric value, add zero (col + 0).
This does not allow for "negative precision", such as "1.2M" being represented as 1200000. If you need that, then Norbert's approach is probably better.
You can store with high precision and exact recall by following a different way of storing the data:
Create a table with two columns:
CREATE TABLE precise (value BIGINT, decimaldot INT);
Use code to determine where the dot is, for example in your 21 value: 2 (assuming 1 indexing). So stored the value would be:
INSERT INTO precise values (21,2);
Retrieved it would return 21 exact (parsing back the dot in the value 21 at position 2, is 21)
Value 17.008 would also have decimaldot at 2:
INSERT INTO precise values (17008,2);
Etc..
Larger values can be stored by using a VARCHAR(4000) instead of a biginteger, or by using blob fields.

How to to insert floats into mysql and then query eqality

Wowee ..does mysql work with floats or not!
1) I insert a float into mysql field
price = 0.1
2) I run the below query:
select * from buy_test where price = 0.1
WOW! I get no results
3) I run the below query:
select * from buy_test where price < 0.1
I get no results
4) I run the below query
select * from buy_test where price > 0.1
YAY! I get results but no..I wanted where price =0.1
How to I insert a float to mysql so I can query a float in mysql
Thanks
CREATE TABLE `buy_test` (
`user_id` varchar(45) DEFAULT NULL,
`order_id` varchar(100) NOT NULL,
`price` float DEFAULT NULL,
`insert_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$
That's because 0.1 doesn't exist in floating point arithmetic.
It would take an infinity number of digits to print the real value of 0.1 in binary (just like it would take an infinity number of digits do print the real value of 10/3).
In your table, you are storing the price with a 'float' type, which is represented on 32 bits. The value 0.1 is rounded to 0.100000001490116119384765625 (which is the nearest representation of 0.1 in the float type format).
When you are requesting all rows where prices are equal to 0.1, I strongly suspect the interpreter to use the double type, or at least, a more precise type than float.
But let's consider it's using the double type on 64 bits.
In the double type, 0.1 is rounded to 0.1000000000000000055511151231257827021181583404541015625 .
When the engines makes the comparison, it leads to:
if (0.100000001490116119384765625 ==
0.1000000000000000055511151231257827021181583404541015625) ...
which is obviously false. But it's true for operator > .
I'm pretty sure that this where clause would work: "where price = 0.100000001490116119384765625"
By the way, when the result of your query tells you that the price is "0.1", it's a lie. The value is rounded to be "beautifully displayed".
There is no real solution to your problem, everybody knowing floating point arithmetic problems will discourage you to use equality comparison on floats.
You may use an epsilon for your request.
There is a very interesting article named "What Every Computer Scientist Should Know About Floating-Point Arithmetic"; you can find it there:
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Anomalous mysql behaviour on replace query

im using a v simple database and i have 3 columns A(bigINT 20) , B(bigInt 20) and c(DECIMAL(5,4)) , when i fire the following query i get the below mentioned results :
REPLACE INTO `my_table` SET `A` = 8,`B` = 44,`C` = 14;
i get these values in mysql A =8 , b= 44 and c as 9.9999 ! ?
any ideas as to why is this happening and what can i do to resolved this ?
DECIMAL(5,4) means that the number has at most 5 digits, 4 of them after decimal point. So 14 is simply overflow as it would require DECIMAL(6,4).
It must be cleared that 14 is overflow, because as constant precision point decimal it is internally 14.0000 here (so six digits over five).
So if you try to put 14.0000 (six digits) in DECIMAL(5,4) (five digits max) -> MySQL chooses value closest to the one you request. Therefore 14.0000 gets "rounded" to 9.9999.
To fit 14 in your column you can either extend it do DECIMAL(6,4) (to allow more digits in general) or change to DECIMAL(5,3) (which will allow one more digit before decimal point, but loses some precision of course).