mysql converting bit to char not working - mysql

I was trying to feed a result of a query as a parameter for another query and all was working fine except this field that has a datatype of bit. so i tried to convert the value of the field using convert() and cast() but it seems to be not working as its returning this wierd symbol of a small rectange which hava three 0's and a 1. so can anyone tell me why this is happening and how to fix it , here is my query
select CONVERT(isMale , char(5)) from person;
and the thing is it gives me the correct answer when i dont use the convert but since am giving this result to another query as a parameter it causing me the problem.

you can use BIN function like this:
SELECT BIN(isMale +0) from person;
sample
MariaDB [yourschema]> SELECT BIN(b'1001' +0) ;
+-----------------+
| BIN(b'1001' +0) |
+-----------------+
| 1001 |
+-----------------+
1 row in set (0.00 sec)
MariaDB [yourschema]>
Here some stuff from MariaDB Manual:
Description
Converts numbers between different number bases. Returns a
string representation of the number N, converted from base from_base
to base to_base.
Returns NULL if any argument is NULL, or if the second or third
argument are not in the allowed range.
The argument N is interpreted as an integer, but may be specified as
an integer or a string. The minimum base is 2 and the maximum base is
36. If to_base is a negative number, N is regarded as a signed number. Otherwise, N is treated as unsigned. CONV() works with 64-bit
precision.
Some shortcuts for this function are also available: BIN(), OCT(),
HEX(), UNHEX(). Also, MariaDB allows binary literal values and
hexadecimal literal values.
BIN is a short form from CONV(value,from,to) where you can convert from base to base
so binary 1001 = 9 as int
here i give the value in decimal (14) and convert it from base 10 to base 2
MariaDB [yourschema]> SELECT CONV(14,10 ,2);
+-----------------+
| CONV(14,10 ,2) |
+-----------------+
| 1110 |
+-----------------+
1 row in set (0.00 sec)
so, if you want to have 0 on the left you can add a value like this
MariaDB [yourschema]> SELECT CONV(8192 + 14,10 ,2);
+------------------------+
| CONV(8192 + 14,10 ,2) |
+------------------------+
| 10000000001110 |
+------------------------+
1 row in set (0.00 sec)
and then you can get n chars from right:
MariaDB [yourschema]> SELECT RIGHT(CONV(8192 + 14,10 ,2),8);
+---------------------------------+
| RIGHT(CONV(8192 + 14,10 ,2),8) |
+---------------------------------+
| 00001110 |
+---------------------------------+
1 row in set (0.40 sec)
MariaDB [yourschema]>

I think you want to use CAST
select CAST(isMale as CHAR) from person;

seeing #Bernd Buffen answer i tried using the convert with +0 and it works , eventhough i dont know why
select CONVERT(isMale +0, char(5)) from person;

Related

MySQL: shorten a column with SUBSTRING

I Am trying to do this:
update student
set student_name=SUBSTRING(student_name, 0, 8)
where student_name like 'MAX%';
So, my intent is to update the column with first 8 chars of the original content.
But the student_name column is getting set to empty value.
Why is this happening? can someone help me fix this
Before update anything, do select with similar request.
MariaDB [(none)]> select SUBSTRING('123456',1,2 ), SUBSTRING('123456',0,2 );
+--------------------------+--------------------------+
| SUBSTRING('123456',1,2 ) | SUBSTRING('123456',0,2 ) |
+--------------------------+--------------------------+
| 12 | |
+--------------------------+--------------------------+
1 row in set (0.00 sec)
MariaDB [(none)]>
Invalid or negative first number in substring resulting empty string.

Why does MariaDB-10.2.8 UNHEX() return NULL?

I have a SQL script that works on MySQL (up to current versions). I built a copy of MariaDB-10.2.8 from source on a Linux machine and got the database up and running. However, my SQL script fails, because MariaDB is returning NULL from an UNHEX() call, where it shouldn't.
The call is producing a 20-byte random binary string in a particular format (it's a BitTorrent node ID). I concatenate some required bytes with some random bytes, with certain bytes being limited to a particular range of values. These are constructed as a 40-character hex string, which I then run through UNHEX().
The SQL is:
unhex( concat( '414C2',
hex( 8 + round( rand() * 7 ) ),
substr( sha( uuid( ) ), 6, 33 ),
hex( 2 + round( rand( ) ) * 8 ) ) )
If you take off the UNHEX() function, you get a 40-character hex string:
MariaDB [bt]> select concat('414c2', hex(8+round(rand()*7)),substr(sha(uuid()),6,33),hex(2+round(rand())*8));
+-----------------------------------------------------------------------------------------+
| concat('414c2', hex(8+round(rand()*7)),substr(sha(uuid()),6,33),hex(2+round(rand())*8)) |
+-----------------------------------------------------------------------------------------+
| 414c29115056f1bd332d4e2e3eb5edd3fc90c0a2 |
+-----------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
but if you UNHEX() it:
MariaDB [bt]> select unhex(concat('414c2', hex(8+round(rand()*7)),substr(sha(uuid()),6,33),hex(2+round(rand())*8)));
+------------------------------------------------------------------------------------------------+
| unhex(concat('414c2', hex(8+round(rand()*7)),substr(sha(uuid()),6,33),hex(2+round(rand())*8))) |
+------------------------------------------------------------------------------------------------+
| NULL |
+------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
By contrast, the same command on a MySQL instance:
mysql> select unhex(upper(concat('414c2', hex(8+round(rand()*7)),substr(sha(uuid()),6,33),hex(2+round(rand())*8))));
+-------------------------------------------------------------------------------------------------------+
| unhex(upper(concat('414c2', hex(8+round(rand()*7)),substr(sha(uuid()),6,33),hex(2+round(rand())*8)))) |
+-------------------------------------------------------------------------------------------------------+
| AL*w??
???r?%?? |
+-------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)
UNHEX() of a 40-character hex string where all the bytes are printable works OK on MariaDB:
MariaDB [bt]> select unhex('4142434445464748494a4b4c4d4e4f5051525354');
+---------------------------------------------------+
| unhex('4142434445464748494a4b4c4d4e4f5051525354') |
+---------------------------------------------------+
| ABCDEFGHIJKLMNOPQRST |
+---------------------------------------------------+
1 row in set (0.00 sec)
Any idea why a random hex string wouldn't work?
Looks like a bug. We've filed a report for this:
https://jira.mariadb.org/browse/MDEV-13793

How to check if a column value contains integers

We have a varchar(255) column and some values are integers, how do I isolate only the rows which contain integer values
This should work.
select *
from table
where column
regexp '^\-?[1-9][0-9]*$'
EDIT: thanks Alma Do for pointing out that my solution did not consider signed integers and leading zeroes! Also his solution is much more performant than using regular expressions.
You can do this with CAST():
SELECT * FROM t WHERE CAST(col AS SIGNED)=col
You can use REGEXP() for your issue, but I will not recommend that: for large tables CAST() will be extremely faster. Compare:
mysql> select benchmark(1E7, '17453454.6655744' REGEXP '^[0-9]+$');
+------------------------------------------------------+
| benchmark(1E7, '17453454.6655744' REGEXP '^[0-9]+$') |
+------------------------------------------------------+
| 0 |
+------------------------------------------------------+
1 row in set (17.59 sec)
With:
mysql> select benchmark(1E7, CAST('17453454.6655744' AS SIGNED)='17453454.6655744');
+-----------------------------------------------------------------------+
| benchmark(1E7, CAST('17453454.6655744' AS SIGNED)='17453454.6655744') |
+-----------------------------------------------------------------------+
| 0 |
+-----------------------------------------------------------------------+
1 row in set, 1 warning (0.36 sec)
-and see the difference.
Here col means, will have to provide column name which has to be checked that having intergers or not ..?
SELECT * FROM t WHERE CAST(col AS SIGNED)=col

MySQL Precison Issues in DECIMAL NUMERIC data type

In writing a function for scientific application, I ran into issues. I traced it back to MySQL's lack of precison.
Here is the page from the official documentation which claims that The maximum number of digits for DECIMAL is 65 - http://dev.mysql.com/doc/refman/5.6/en/fixed-point-types.html . It also describes how the value will be rounded if it exceeds the specified precison.
Here is reproducible code (a mysql stored function) to test it -
DELIMITER $$
DROP FUNCTION IF EXISTS test$$
CREATE FUNCTION test
(xx DECIMAL(30,25)
)
RETURNS DECIMAL(30,25)
DETERMINISTIC
BEGIN
DECLARE result DECIMAL(30,25);
SET result = 0.339946499848118887e-4;
RETURN(result);
END$$
DELIMITER ;
If you save the code above in a file called test.sql, you can run it by executing the following in mysql prompt -
source test.sql;
select test(0);
It produces the output -
+-----------------------------+
| test(0) |
+-----------------------------+
| 0.0000339946499848118900000 |
+-----------------------------+
1 row in set (0.00 sec)
As you can see, the number is getting rounded at the 20th digit, and then five zeroes are being added to it to get to the required/specified precison. That is cheating.
Am I mistaken, or is the documentation wrong?
This happens because mysql treats 0.339946499848118887e-4 as float and treats 0.0000339946499848118887 as fixed point.
mysql> select cast( 0.339946499848118887e-4 as DECIMAL(30, 25));
+----------------------------------------------------+
| cast( 0.339946499848118887e-4 as DECIMAL(30, 25)) |
+----------------------------------------------------+
| 0.0000339946499848118900000 |
+----------------------------------------------------+
1 row in set (0.00 sec)
mysql> select cast( 0.0000339946499848118887 as DECIMAL(30, 25));
+-----------------------------------------------------+
| cast( 0.0000339946499848118887 as DECIMAL(30, 25)) |
+-----------------------------------------------------+
| 0.0000339946499848118887000 |
+-----------------------------------------------------+
1 row in set (0.00 sec)
As described in the mysql documentation on precision math - expression handling -
If any approximate values are present, the expression is approximate and is evaluated using floating-point arithmetic.
Quoting from, the documentation on numerical types,
Two numbers that look similar may be treated differently. For example, 2.34 is an exact-value (fixed-point) number, whereas 2.34E0 is an approximate-value (floating-point) number.
I don't know anything about SQL, but my guess would be this line:
SET result = 0.339946499848118887e-4;
If MySQL is anything like other languages I know, then this will first evaluate the right-hand side, and then assign the value to result. No matter what type result is declared to be or what precision it's declared to have, it wouldn't matter if the right-hand side has already lost precision when being evaluated. This is almost surely what is happening here.
I can reproduce your results, but If I change that line to
SET result = cast('0.339946499848118887e-4' as decimal(30, 25));
(casting from a string instead of from a floating-point constant of unspecified precision) then I correctly get
+-----------------------------+
| test(0) |
+-----------------------------+
| 0.0000339946499848118887000 |
+-----------------------------+
1 row in set (0.00 sec)
as desired. So that's your fix.
BTW, the documentation that scale in DECIMAL(precision, scale) cannot be greater than 30 seems to be in section 12.19.2. DECIMAL Data Type Changes:
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.

How can I convert a string to a float in mysql?

I have a table containing latitude and longitude values stored as strings (VARCHAR) which I'd like to convert to FLOAT (10,6).
However there doesn't appear to be a straightforward way to do this using CAST() or CONVERT().
How can I convert these columns easily? This is a one-time conversion.
It turns out I was just missing DECIMAL on the CAST() description:
DECIMAL[(M[,D])]
Converts a value to DECIMAL data type. The optional arguments M and D specify the precision (M specifies the total number of digits) and the scale (D specifies the number of digits after the decimal point) of the decimal value. The default precision is two digits after the decimal point.
Thus, the following query worked:
UPDATE table SET
latitude = CAST(old_latitude AS DECIMAL(10,6)),
longitude = CAST(old_longitude AS DECIMAL(10,6));
mysql> SELECT CAST(4 AS DECIMAL(4,3));
+-------------------------+
| CAST(4 AS DECIMAL(4,3)) |
+-------------------------+
| 4.000 |
+-------------------------+
1 row in set (0.00 sec)
mysql> SELECT CAST('4.5s' AS DECIMAL(4,3));
+------------------------------+
| CAST('4.5s' AS DECIMAL(4,3)) |
+------------------------------+
| 4.500 |
+------------------------------+
1 row in set (0.00 sec)
mysql> SELECT CAST('a4.5s' AS DECIMAL(4,3));
+-------------------------------+
| CAST('a4.5s' AS DECIMAL(4,3)) |
+-------------------------------+
| 0.000 |
+-------------------------------+
1 row in set, 1 warning (0.00 sec)
This will convert to a numeric value without the need to cast or specify length or digits:
STRING_COL+0.0
If your column is an INT, can leave off the .0 to avoid decimals:
STRING_COL+0