Integers and decimals to varchar sql-server - sql-server-2008

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.

Related

MySQL Workbench out of range value for decimal number

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.

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.

I need a trigger to create id's in my sql database with a string and some zeros

I'm currently using this trigger which adds id's with 3 zeros and two zeros and then the id from the sequences table.
BEGIN
INSERT INTO sequences VALUES (NULL);
SET NEW.deelnemernr = CONCAT('ztmr16', LPAD(LAST_INSERT_ID(), 3, '0'));
END
I changed the 3 to 4 but then it didn't increment the id anymore, resulting in and multiple id error. It stayed at ztmr16000. So what can I do to add more zeros and still get the id from the sequencestable?
The MySQL LPAD function limits the number of characters returned to the specified length.
The specification is a bit unclear, what you are trying to achieve.
If I need a fixed length string with leading zeros, my approach would be to prepend a boatload of zeros to my value, and then take the rightmost string, effectively lopping off extra zeros from the front.
To format a non-negative integer value val into a string that is ten characters in length, with the leading characters as zeros, I'd do something like this:
RIGHT(CONCAT('000000000',val),10)
As a demonstration:
SELECT RIGHT(CONCAT('000000000','123456789'),10) --> 0123456789
SELECT RIGHT(CONCAT('000000000','12345'),10) --> 0000012345
Also, I'd be cognizant of the maximum length allowed in the column I was populating, and be sure that the length of the value I was generating didn't exceed that, to avoid data truncation.
If the value being returned isn't be truncated when it's inserted into the column, then what I think the behavior you observe is due to the value returned from LAST_INSERT_ID() exceeding 1000.
Note that for a non-negative integer value val, the expression
LPAD(val,3,'0')
will allow at most 1000 distinct values. LPAD (as I noted earlier) restricts the length of the returned string. In this example, to three characters. As a demonstration of the behavior:
SELECT LPAD( 21,3,'0') --> 021
SELECT LPAD( 321,3,'0') --> 321
SELECT LPAD( 54321,3,'0') --> 543
SELECT LPAD( 54387,3,'0') --> 543
There's nothing illegal with doing that. But you're going to be in trouble if you depend on that to generate "unique" values.
FOLLOWUP
As stated, the specification ...
"adds id's with 3 zeros and two zeros and then the id from the sequences table."
is very unclear. What is it exactly that you want to achieve? Consider providing some examples. It doesn't seem like there's an issue concatenating something to those first five fixed characters. The issue seems to be with getting the id value "formatted" to your specification
This is just a guess of what you are trying to achieve:
id value formatted return
-------- ----------------
1 0001
9 0009
22 0022
99 0099
333 0333
4444 4444
55555 55555
666666 666666
You could achieve that with something like this:
BEGIN
DECLARE v_id BIGINT;
INSERT INTO sequences VALUES (NULL);
SELECT LAST_INSERT_ID() INTO v_id;
IF ( v_id <= 9999 ) THEN
SET NEW.deelnemernr = CONCAT('ztmr16',LPAD(v_id,4,'0'));
ELSE
SET NEW.deelnemernr = CONCAT('ztmr16',v_id);
END IF;
END

mysql calculation result forcefully rounded

I have this field:
user_id VARCHAR(20);
insert_date DATE;
fgps DECIMAL(5,2);
in a table, and is calculating the value using these (simplified) statements:
-- #num1, 2 and 3 are SET with some query to get the values
SET #gps_average := ((#num1 + #num2 + #num3) / 3.0);
INSERT INTO user_gps VALUES(:user_id, :insert_date, #gps_average);
The script is working fine, except for one thing -- the result of #gps_average is forced to be rounded by the mysql server. i.e. if I have the values
#num1=3, #num2=4, #num3=4
I should get 3.67 stored in fgps, but instead 4.00 is what I got.
What have I done wrong or how do I force the server to no round up my values?
I've done similar calculations on some other fields and the values are stored with decimal values correctly, but not in this case, this is driving me crazy...
Thanks in advance.

Single quotes affecting the calculations in Select query

SELECT COUNT(*) FROM area
WHERE ROUND(SQRT(POWER(('71' - coords_x), 2) +
POWER(('97' - coords_y), 2))) <= 17
==> 51
SELECT COUNT(*) FROM area
WHERE ROUND(SQRT(POWER((71 - coords_x), 2) +
POWER((97 - coords_y), 2))) <= 17
==> 22
coords_x and coords_y are both TINYINT fields containing values in the range [1, 150]. Usually MySQL doesn't care if numbers are quoted or not.. but apparently it does in this case.
The question is just: Why?
MySQL always cares about data types. What happens is that your code relies in automatic type casting and performs math on strings (which can hold a number or not). This can lead to all sort of unpredictable results:
SELECT POW('Hello', 'World') -- This returns 1
To sum up: you need to learn and use the different data types MySQL offers. Otherwise, your application will never do reliable calculations.
Update:
One more hint:
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
A very small integer. The signed range
is -128 to 127. The unsigned range is
0 to 255.
URL:
http://dev.mysql.com/doc/refman/5.1/en/numeric-type-overview.html
I hope you are not trying to store 150 in a signed tinyint column.