my_table contains the enabled field which is defined as: enabled BIT NOT NULL DEFAULT 0.
This table has multiple rows with enabled = b'0', and multiple rows with enabled = b'1'.
However, both this:
SELECT * from my_table WHERE enabled = b'0';
and this:
SELECT * from my_table WHERE enabled = b'1';
show blank in the enabled column:
+----+---------+
| id | enabled |
+----+---------+
| 1 | |
| 2 | |
+----+---------+
Why is that? How could I see the value of the enabled field?
$ mysql --version
mysql Ver 14.14 Distrib 5.1.63, for debian-linux-gnu (x86_64) using readline 6.1
The reason why you can't see it in terminal is because bit values are non printable characters.
Lets insert following values:
INSERT INTO `my_table` (`ID`, `enabled`)
VALUES (1,b'1'),(2,b'0');
Then select them to file:
mysql> SELECT * FROM my_table INTO OUTFILE '/tmp/my_table.txt' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';
First lets view our /tmp/my_table.txtfile as plain text:
"1"," "
"2"," "
and then in hex view:
22 31 22 2C 22 01 22 0A 22 32 22 2C 22 00 22 0A
To be able to see those values you can simply CAST them in SELECT:
SELECT id, CAST(enabled AS UNSIGNED) AS enabled FROM my_table
And that will produce the following output:
+----+---------+
| id | enabled |
+----+---------+
| 1 | 1 |
| 2 | 0 |
+----+---------+
2 rows in set (0.00 sec)
Another way you can do it is
SELECT enabled+0 from my_table
the simplest way is ORD function:
SELECT ORD(`enabled`) AS `enabled` FROM `my_table`
Bit values are returned as binary values. To display them in printable form, add 0 or use a conversion function such as BIN().
https://dev.mysql.com/doc/refman/5.7/en/bit-field-literals.html
Use HEX()
Like:
SELECT id, HEX(enabled) AS enabled FROM my_table
You could also try SELECT enabled&1 from my_table.
to convert a bit field value to a human readable string, use the built-in EXPORT_SET function, the simple example to convert a column of type bit(1) to a "Y" or "N" value would be
EXPORT_SET(column, 'Y', 'N')
You could also convert a bit(8) value to binary representation of the byte
EXPORT_SET(column, '1', '0', '', 8)
Related
I have a query like so:
SELECT * FROM `mytable` WHERE `code` LIKE 'PR-SM' AND number = '45'
However in some instances the number can be PR45 which will then fail. I have tried the following:
SELECT * FROM `mytable` WHERE `code` LIKE 'PR-SM' AND CAST(number as unsigned) = '45'
SELECT * FROM `mytable` WHERE `code` LIKE 'PR-SM' AND CONVERT(number as unsigned) = '45'
SELECT * FROM `mytable` WHERE `code` LIKE 'PR-SM' AND number LIKE '%45'
LIKE % will not work as it also picks up 145.
REGEXP_REPLACE also does not work as I am on MySQL 5.7
This is needed for my API, because of my setup I need to be able to do it in the where clause.
Sample Table:
+--------------------------+
| code | number |
+--------------------------+
| PR-SM | PR45 |
+--------------------------+
| PR-SM | PR145 |
+--------------------------+
| XYZ | 177 |
+--------------------------+
| XYZ | 81 |
+--------------------------+
Although you are not using MySQL 8+, which means you won't have access to the newer regex functions, on 5.7 REGEXP should still be available:
SELECT *
FROM yourTable
WHERE code = 'PR-SM' AND number REGEXP '(^|[^0-9])45([^0-9]|$)';
Demo
The regex pattern used here says to match:
(^|[^0-9]) match the start of the input OR a non digit
45 match the number 45
([^0-9]|$) match the end of the input OR a non digit
I have to always get the last 5 digits from a string and need to convert it to int.
But I have situations where the 5th digit from the end is a character.
If I have the a character then I want to just get the number.
Sample data:
Input Expected Output
978568-16258 16258
ERGF99252697 52697
SP-988824-189241 89241
SP-456790-568723 68723
SP-456790-568 568
I'have tried some thing like this:
select CAST((RIGHT(RTRIM(col_1),5)) AS UNSIGNED INT) as test from table_A;
For few of the reults its ok but when it sees characters then it displays a random number.
How can I resolve this issue?
If you are running MySQL 8.0 / MariaDB 10.0.5, you can use regexp_substr() for this. This should be as simple as:
select cast(regexp_substr(col_1, '[0-9]{1,5}$') as unsigned) from table_A
Regexp '[0-9]{1,5}$' means: as many digits as possible (maximum 5) at the end of the string.
Demo on DB Fiddle:
col_1 | col_1_new
:--------------- | :--------
978568-16258 | 16258
ERGF99252697 | 52697
SP-988824-189241 | 89241
SP-456790-568723 | 68723
SP-456790-568 | 568
For older versions of MySQL/MariaDB, you can do:
select cast(right(col_1,
(col_1 regexp "[0-9]{1}$") +
(col_1 regexp "[0-9]{2}$") +
(col_1 regexp "[0-9]{3}$") +
(col_1 regexp "[0-9]{4}$") +
(col_1 regexp "[0-9]{5}$")
) as unsigned) from table_A;
I have mysql table with multiple columns, a column has string data type namely code and the values of the column might be digits only or mixed of string and digits e.g: one row value has 57677 and other rows column value like 2cskjf893 or 78732sdjfh.
mysql> select * from testuser;
+------+--------------+
| id | code |
+------+--------------+
| 1 | 232 |
| 2 | adfksa121dfk |
| 3 | 12sdf |
| 4 | dasd231 |
| 5 | 897 |
+------+--------------+
5 rows in set (0.00 sec)
mysql> show create table testuser;
+----------+------------------------------------------------------------------ ---------------------------------------------------------------+
| Table | Create Table |
+----------+------------------------------------------------------------------ ---------------------------------------------------------------+
| testuser | CREATE TABLE `testuser` (
`id` int(11) DEFAULT NULL,
`code` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+------------------------------------------------------------------ ---------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
I would like to filter out only rows which has numeric value in code column or filter rows which has string values in code column.
try this
Mysql Query to fetch only integer values from a particular column
SELECT column FROM TABLE where column NOT REGEXP '^[0-9]+$' ;
Mysql Query to fetch only string values from a particular column
SELECT column FROM TABLE where column REGEXP '^[0-9]+$' ;
To get digits
SELECT id,code
FROM table_name
WHERE code REGEXP '^[0-9]+$';
To get string values
SELECT *
FROM table_name
WHERE code REGEXP '^[a-zA-Z]+$'
Use regular expressions
SELECT *
FROM myTable
WHERE code REGEXP '^[0-9]+$';
This will filter out column values with all digits.
You can use regular expressions in mysql too.
SELECT * FROM `table` WHERE `code` REGEXP '[0-9]';
Results will be the rows, where any number in the code column.
Try this,
select id,code from table_name where code NOT REGEXP '^[0-9]+$'
Or,
select id,code from table_name where code like '%[^0-9]%'
What's the right syntax to insert a value inside a column of type bit(1) in `MySQL'?
My column definition is:
payed bit(1) NOT NULL
I'm loading the data from a csv where the data is saved as 0 or 1.
I've tried to do the insert using:
b'value' or 0bvalue (example b'1' or 0b1)
As indicated from the manual.
But I keep getting this error:
Warning | 1264 | Out of range value for column 'payed' at row 1
What's the right way to insert a bit value?
I'm not doing the insert manually but I'm loading the data from a csv (using load data infile) in which the data for the column is 0 or 1.
This is my load query, I've renamed the fields for privacy questions, there's no error in that definition:
load data local infile 'input_data.csv' into table table
fields terminated by ',' lines terminated by '\n'
(id, year, field1, #date2, #date1, field2, field3, field4, field5, field6, payed, field8, field9, field10, field11, project_id)
set
date1 = str_to_date(#date1, '%a %b %d %x:%x:%x UTC %Y'),
date2 = str_to_date(#date2, '%a %b %d %x:%x:%x UTC %Y');
show warnings;
This is an example row of my CSV:
200014,2013,0.0,Wed Feb 09 00:00:00 UTC 2014,Thu Feb 28 00:00:00 UTC 2013,2500.0,21,Business,0,,0,40.0,0,PROSPECT,1,200013
Update:
I didn't find a solution with the bit, so I've changed the column data type from bit to tinyint to make it work.
I've finally found the solution and I'm posting it here for future reference. I've found help in the mysql load data manual page.
So for test purpose my table structure is:
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| nome | varchar(45) | YES | | NULL | |
| valore | bit(1) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
My csv test file is:
1,primo_valore,1
2,secondo_valore,0
3,terzo_valore,1
The query to load the csv into the table is:
load data infile 'test.csv' into table test
fields terminated by ',' lines terminated by '\n'
(id, nome, #valore) set
valore=cast(#valore as signed);
show warnings;
As you can see do load the csv you need to do a cast cast(#valore as signed) and in your csv you can use the integer notation 1 or 0 to indicate the bit value. This is because BIT values cannot be loaded using binary notation (for example, b'011010').
Replace the "0" values in the csv by no value at all. That worked for me.
You can use BIN() function like this :
INSERT INTO `table` VALUES (`column` = BIN(1)), (`column` = BIN(0));
Let me guess, but I think you should ignore 1st line of your CSV file in LOAD query.
See "IGNORE number LINES"
For example - I create database and a table from cli and insert some data:
CREATE DATABASE testdb CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
USE testdb;
CREATE TABLE test (id INT, str VARCHAR(100)) TYPE=innodb CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
INSERT INTO test VALUES (9, 'some string');
Now I can do this and these examples do work (so - quotes don't affect anything it seems):
SELECT * FROM test WHERE id = '9';
INSERT INTO test VALUES ('11', 'some string');
So - in these examples I've selected a row by a string that actually stored as INT in mysql and then I inserted a string in a column that is INT.
I don't quite get why this works the way it works here. Why is string allowed to be inserted in an INT column?
Can I insert all MySQL data types as strings?
Is this behavior standard across different RDBMS?
MySQL is a lot like PHP, and will auto-convert data types as best it can. Since you're working with an int field (left-hand side), it'll try to transparently convert the right-hand-side of the argument into an int as well, so '9' just becomes 9.
Strictly speaking, the quotes are unnecessary, and force MySQL to do a typecasting/conversion, so it wastes a bit of CPU time. In practice, unless you're running a Google-sized operation, such conversion overhead is going to be microscopically small.
You should never put quotes around numbers. There is a valid reason for this.
The real issue comes down to type casting. When you put numbers inside quotes, it is treated as a string and MySQL must convert it to a number before it can execute the query. While this may take a small amount of time, the real problems start to occur when MySQL doesn't do a good job of converting your string. For example, MySQL will convert basic strings like '123' to the integer 123, but will convert some larger numbers, like '18015376320243459', to floating point. Since floating point can be rounded, your queries may return inconsistent results. Learn more about type casting here. Depending on your server hardware and software, these results will vary. MySQL explains this.
If you are worried about SQL injections, always check the value first and use PHP to strip out any non numbers. You can use preg_replace for this: preg_replace("/[^0-9]/", "", $string)
In addition, if you write your SQL queries with quotes they will not work on databases like PostgreSQL or Oracle.
Check this, you can understand better ...
mysql> EXPLAIN SELECT COUNT(1) FROM test_no WHERE varchar_num=0000194701461220130201115347;
+----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+
| 1 | SIMPLE | test_no | index | Uniq_idx_varchar_num | Uniq_idx_varchar_num | 63 | NULL | 3126240 | Using where; Using index |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+------+---------+--------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT COUNT(1) FROM test_no WHERE varchar_num='0000194701461220130201115347';
+----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+
| 1 | SIMPLE | test_no | const | Uniq_idx_varchar_num | Uniq_idx_varchar_num | 63 | const | 1 | Using index |
+----+-------------+------------------------+-------+-------------------+-------------------+---------+-------+------+-------------+
1 row in set (0.00 sec)
mysql>
mysql>
mysql> SELECT COUNT(1) FROM test_no WHERE varchar_num=0000194701461220130201115347;
+----------+
| COUNT(1) |
+----------+
| 1 |
+----------+
1 row in set, 1 warning (7.94 sec)
mysql> SELECT COUNT(1) FROM test_no WHERE varchar_num='0000194701461220130201115347';
+----------+
| COUNT(1) |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)
AFAIK it is standard, but it is considered bad practice because
- using it in a WHERE clause will prevent the optimizer from using indices (explain plan should show that)
- the database has to do additional work to convert the string to a number
- if you're using this for floating-point numbers ('9.4'), you'll run into trouble if client and server use different language settings (9.4 vs 9,4)
In short: don't do it (but YMMV)
This is not standard behavior.
For MySQL 5.5. this is the default SQL Mode
mysql> select ##sql_mode;
+------------+
| ##sql_mode |
+------------+
| |
+------------+
1 row in set (0.00 sec)
ANSI and TRADITIONAL are used more rigorously by Oracle and PostgreSQL. The SQL Modes MySQL permits must be set IF AND ONLY IF you want to make the SQL more ANSI-compliant. Otherwise, you don't have to touch a thing. I've never done so.
It depends on the column type!
if you run
SELECT * FROM `users` WHERE `username` = 0;
in mysql/maria-db you will get all the records where username IS NOT NULL.
Always quote values if the column is of type string (char, varchar,...) otherwise you'll get unexpected results!
You don't need to quote the numbers but it is always a good habit if you do as it is consistent.
The issue is, let's say that we have a table called users, which has a column called current_balance of type FLOAT, if you run this query:
UPDATE `users` SET `current_balance`='231608.09' WHERE `user_id`=9;
The current_balance field will be updated to 231608, because MySQL made a rounding, similarly if you try this query:
UPDATE `users` SET `current_balance`='231608.55' WHERE `user_id`=9;
The current_balance field will be updated to 231609