MySQL Single Quote Efficiency - mysql

I live in Australia, so postcodes are numeric and four digits long.
In a table steup by another person the postcode field has been setup as a VARCHAR(10) - strange i know!!!
There is a difference between the following two query times:
Postcode='3000'
Postcode=3000
Both queries run, but the one with single quotes around it runs between 50% to 80% faster. Likewise postcode IN('3000','3001','3002') is much faster than Postcode IN(3000,3001,3002). The postcode field is indexed
The quesiton is HOW do the single quotes make so much speed difference?
Can anyone shed any light on how the engine optimizes the above queries?

There is one important trap in this.
If you use something like
code = 1000
instead of
code = '1000'
then if you had other dataset, the first case would return all records like:
'1000', '1000A', '1000B'
etc, while the second would return as expected only '1000'. This might be the reason of performance issue. Some mentioned that it converts int to varchar. I believe it converts all varchars to int and that is why it is noticable

When you don't include the quotes, the interpreter has to take the time to do an implicit conversion from int to varchar. If you use quotes, it's already a varchar and it saves the time of doing a conversion to the native storage format.

Related

Mysql where clause comparison give different result for double and float data type for same value

My mysql version is 5.7.14
I have 1 table with two column
1). price_val_float with float data type
2). price_val_double with double data type
Table structure
CREATE TABLE test (
price_val_float FLOAT(6,2),
price_val_double DOUBLE(6,2)
);
Same value in both column
INSERT INTO test VALUES
(78.59, 78.59),
(78.60, 78.60),
(78.61, 78.61);
Now I set one variable as follow
SET #priceValue=78.6;
Now I want to get all record from test table where price_val_float >= #priceValue;
SELECT price_val_float FROM test WHERE price_val_float>= #priceValue;
above query return only 78.61
But if I run same query of price_val_double column
SELECT price_val_double FROM test WHERE price_val_double>= #priceValue;
This return
78.60
78.61
I am not getting why mysql return different result as only data type is different.
Does anyone knows about this ?
Here is Fiddle for testing
Thanks in advance.
This might sound strange to say but this is because decimal numbers are approximates values. This is an issue across all programming due to the nature of storing large numbers. Even the mysql documentation calls these "approximate" values:
https://dev.mysql.com/doc/refman/5.5/en/floating-point-types.html
For example: MySQL performs rounding when storing values, so if you insert 999.00009 into a FLOAT(7,4) column, the approximate result is 999.0001.
This is explained in the mysql documentation here:
https://dev.mysql.com/doc/refman/5.5/en/problems-with-float.html
Or as an additional case explained in Python here:
https://docs.python.org/2/tutorial/floatingpoint.html
The way to get around this is identify the precision you want and store the value as an integer.
Float is a single precision and Double is for double precision that why your getting the difference.
This is happening because the difference between the numbers shows up around the tenth decimal or so, depending on factors such as computer architecture or the compiler version or optimization level. For example, different CPUs may evaluate floating-point numbers differently.
You need to use DECIMAL data type for more accurate results. Also check this for more details
That is because Float point values are not stored as exact values. If you need exact value you can use Decimal data type. You can read about it here

Why this MySQL Query Successfully Executes?

I am playing with Multilldae's XSS exercise and in one of the exercise(OWASP 2013->A3->Reflected->Pen Test Tool Lookup) my crafted input lead to the following query. The where clause is in a very strange form. And tool_id is an int field.
SELECT tool_id, tool_name, phase_to_use, tool_type, comment FROM pen_test_tools
WHERE tool_id = '2\", \"good\":\"haha';
Surprising to me, this query successfully executes and returns the correct result. Could you please tell me why? In my view, the where clause is completely nonsense and MySQL should report an error.
Thanks!
The reason is because tool_id is an integer, so the comparison is done numerically.
MySQL will convert a string to a number in a numeric context. When it does so, it does
"silent" conversion, so errors are not reported. It converts a string based on the leading numbers, so this string becomes 2. If there are no leading digits (or minus signs or plus signs after leading spaces), then the value is 0.

How do I insert proper std code in mysql

I am making a small project in which I am using mysql for my database, in which i need to input phone numbers with std codes.
The problem is in inserting proper std codes.
Suppose the std code is 0123 but while running the query it is only inserting 123.
If it is 0275, it is only inserting 275.
but if it is 2210 it is properly inserting 2210
i tried making it "int", "bigint", "varchar" but all in vain..
plz sggst to solve it..
Try with this.It should work varchar(5)
I usually store phone numbers as a BIGINT in E164 format.
E164 never start with a 0, with the first few digits being the country code.
+441234567890
+44 (0)1234 567890
01234 567890
etc. would be stored as 441234567890.
But my suggestion is you can use a varchar for a telephone number.
You do not need an int because you are not going to perform arithmetic
on the numbers.
VARCHAR will work in your case.
The only thing you have to make sure is, while inserting the data, you're traeting the data as string, that is enclosing with single quotes. Otherwise, you will again end up losing leading zeroes, doesn't matter you have VARCHAR as the datatype
INSERT INTO tab VALUES('0123');

Why phone numbers in MySQL database are being truncated

I have created a database table in mySQL of which two column names are "landPhone" and "mobilePhone" to store phone numbers (in the format of: 123-456-8000 for land and 098-765-6601 for mobile). These two columns' data type are set to VARCHAR(30). The data have been inserted in the table. But after SQL query, I found the phone numbers have been truncated. It shows (above two data for example) only first 3 digits (123) for landPhone and only first 2 digits after removing the leading '0' (98) for mobilePhone.
Why this is happening ?
Phone numbers are not actually numbers; they are strings that happen to contain digits (and, in your case, dashes). If you try to interpret one as a number, two things typically happen:
Leading zeros are forgotten.
Everything from the first non-digit to the end of the string is stripped off.
That sounds exactly like the result you're describing. Even if you end up stuffing the result into a string field, it's too late -- the data has already been corrupted.
Make sure you're not treating phone numbers as integers at any point in the process.
You must use
insert into sample values('123-456-8000', '098-765-6601' )
instead of
insert into sample values(123-456-8000, 098-765-6601 )
see this SQLFiddle.
Thanks all for your solution. As cHao suspected, it was me who did the mistake. When I first time created the table, I declared the datatype of the phone columns as INT, later I corrected them to VARCHAR().
When I dropped the table and inserted the same data to the new table, it is working fine.
That sounds exactly like the result you're describing. Even if you end up stuffing the result into a string field, it's too late -- the data has already been corrupted. ..cHao
Question to understand: Why mySQL doesn't override the previous datatype with the new one ?

MySQL Tri-state field

I need to create a good/neutral/bad field. which one would be the more understandable/correct way.
A binary field with null (1=good, null=neutral, 0=bad)
An int (1=good, 2=neutral, 3=bad)
An enum (good, neutral, bad)
Any other
It's only and informative field and I will not need to search by this.
NULL values should be reserved for either:
unknown values; or
not-applicable values;
neither of which is the case here.
I would simply store a CHAR value myself, one of the set {'G','N','B'}. That's probably the easiest solution and takes up little space while still providing mnemonic value (easily converting 'G' to 'Good' for example).
If you're less concerned about space, then you could even store them as varchar(7) or equivalent and store the actual values {'Good','Neutral','Bad'} so that no translation at all would be needed in your select statements (assuming those are the actual values you will be printing).
In Mysql you ought to be using an enum type. You can pick any names you like without worrying about space, because Mysql stores the data as a short integer. See 10.4.4. The ENUM Type in the documentation.