When i write this query
SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id = 260;
return
title city
--------------- ------
Butterfly world Mohali
and when i write
SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id = '260abcxyz';
return
title city
--------------- ------
Butterfly world Mohali
see the second one is wrong. i want to get the value only IF ID EXACTLY MATCH ... how to solve this. thanks for your help.
You could convert the id to a string so the comparison will be done exactly. You could use LIKE to cause an implicit conversion
SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id LIKE '260abcxyz';
or alternative, you can perform the cast explicitly
SELECT cd.title, cd.city FROM coupon_detail cd WHERE CAST(cd.id AS CHAR) = '260abcxyz';
However, if all your IDs are integers, it's probably more appropriate to check these values before you try to query the database. (If the ID you're querying with isn't a number, there can't be a match anyway.)
This is happening because of Type Conversion in MySql. My sql treats '260abcxyz' as an integer in your query and AFAIK because first char is number MySql casts it to a number and it becomes only 260 and that's why you are getting result. If you write character first like 'abcxyz260' it will successes the comparison.
More explanation available here: Type Conversion in MySql
As a solution: you should take care that only numbers are passed in comparison and not combination of string and number.
Well, you should not use quote if the id is INT. The way MySQL does is if you use String to compare a INT, it uses just the valid initial integer from start.
see this:
mysql> desc coupon_detail;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| title | varchar(100) | YES | | NULL | |
| city | varchar(100) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.04 sec)
mysql> SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id = 'ff260';
Empty set, 1 warning (0.00 sec)
mysql> SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id = '260ff';
+-----------------+--------+
| title | city |
+-----------------+--------+
| Butterfly world | Mohali |
+-----------------+--------+
1 row in set, 1 warning (0.00 sec)
mysql> SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id = 260;
+-----------------+--------+
| title | city |
+-----------------+--------+
| Butterfly world | Mohali |
+-----------------+--------+
1 row in set (0.00 sec)
mysql> SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id = 26011;
Empty set (0.00 sec)
The idea is not to mix numbers and aphabets to compare a INT column. If you have to you may consider
converting ID column to VARCHAR. In that case auto-increment may go away.
have application logic to query only the strings that has numerics.
use like instead = because if the string is too long than exact match won't work in that way
SELECT cd.title, cd.city FROM coupon_detail cd WHERE cd.id LIKE '260abcxyz';
Related
How can I make MySQL auto increment in 4 digit format?
So instead of '1' make '0001'?
Try adding ZEROFILL attribute to the field.
Could you leave it as an integer and format it for humans in your SQL, for example, to pad with zeros to 4 chars wide
select lpad(idcolumn,4,'0') from mytable;
Or use zerofill and specify the desired width when declaring the table:
create table tmpfoo (
mykey int(6) zerofill not null auto_increment,
primary key(mykey)
);
insert into tmpfoo values(1),(2);
select * from tmpfoo;
+--------+
| mykey |
+--------+
| 000001 |
| 000002 |
+--------+
MySQL supports ZEROFILL on integer columns:
mysql> create table foo (the_key int unsigned zerofill not null
auto_increment primary key);
Query OK, 0 rows affected (0.21 sec)
mysql> insert into foo SET the_key = Null;
Query OK, 1 row affected (0.00 sec)
...
mysql> insert into foo SET the_key = Null;
Query OK, 1 row affected (0.00 sec)
mysql> select * from foo;
+------------+
| the_key |
+------------+
| 0000000001 |
| 0000000002 |
| 0000000003 |
| 0000000004 |
| 0000000005 |
| 0000000006 |
| 0000000007 |
| 0000000008 |
+------------+
8 rows in set (0.00 sec)
You may need to look into using a smallint (5 digits), or trimming/padding.
If you need the auto_increment column in a zero padded format, I suggest that you display it as such and not attempt to store it in the database that way.
In PHP, you could use the following code to display or otherwise use the id:
$padded_id = str_pad($id, 4, '0');
To pad in the database set the id column to ZEROFILL
But if its for display purposes only I recommend using LPAD
SELECT RIGHT('000000' + yourNum, 6);
is the field an integer? if so, the answer is, "why? it's an integer!" ;-)
I'm trying to write an update that will increment the value of auth_id; however, if there is no value, I'd like to set it to 1. I can't even get the select to give me a 0 value to increment.
mysql> describe sequences;
+---------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------------------+------+-----+---------+-------+
| auth_id | int(5) unsigned zerofill | NO | | 00000 | |
+---------+--------------------------+------+-----+---------+-------+
I thought this would work.
mysql> select ifnull(auth_id,0) from sequences;
Empty set (0.00 sec)
Or this...
mysql> select coalesce(auth_id, 0) from sequences;
Empty set (0.00 sec)
What am I missing?
This seems to work:
select ifnull(sequences.auth_id, x.auth_id) as auth_id from sequences right join (select 1 as auth_id) x on 1;
The assumption is that there's only 1 row in sequences. The trick is to make a right join to a fake table with only one row of its own, and then use the ifnull to get the wanted value.
I am trying to query for rows that are not in another set of rows. However, the other set of rows may contain strings that include strings from the first table.
I'm confusing myself trying to explain so I'll use the following example tables:
mysql> DESCRIBE tablea;
+------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| name | char(40) | NO | PRI | | |
+------------+----------+------+-----+---------+-------+
mysql> DESCRIBE tableb;
+------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| nametag | char(40) | NO | PRI | | |
+------------+----------+------+-----+---------+-------+
mysql> SELECT name FROM tablea;
+------------+
| name |
+------------+
| cat |
| dog |
| cow |
+------------+
mysql> SELECT nametag FROM tableb;
+------------+
| nametag |
+------------+
| wolf |
| dog |
| browncow |
+------------+
I am trying to find a method similar to the NOT IN operation, however because cow is "in" browncow, I also want to exclude this value.
mysql> SELECT name FROM tablea WHERE name NOT IN ( SELECT nametag FROM tableb );
+------------+
| name |
+------------+
| cat |
| cow |
+------------+
# I am looking for something that would only return "cat" for this example.
Is there any operation where I can search for rows that aren't contained in another set with additional modifiers?
You could use an anti-join pattern, with a LIKE predicate to do the matching. (The anti-join is an outer join, to return all the rows from one table, along with matches from another table, and then a predicate to exclude the rows that had a match
SELECT a.name
FROM tablea a
JOIN tableb b
ON b.nametag LIKE CONCAT('%',a.name,'%')
WHERE b.nametag IS NULL
(Any rows from a that had a matching row from b... the row from b will have a non-NULL value. Or, to put it another way... rows from a that didn't have a matching row in b will have a NULL value for the columns from b.)
If there's a row in a that has name='cow', and a row from b that has nametag='browncow', those rows will match.
The row from a with name='cat' will only be returned if the string 'cat' doesn't appear in any values of b.nametag.
NOTE: The percent and underscore characters are wildcards in the LIKE predicate. If you want to do matching on those characters, you'd need to "escape" those with a backslash. There's similar issues using a REGEXP match, but a lot more possible mischievous characters.
There are other query patterns that will return an equivalent result.
For example:
SELECT a.name
FROM tablea a
WHERE NOT EXISTS
( SELECT 1
FROM tableb b
WHERE b.nametag LIKE CONCAT('%',a.name,'%')
)
Personally, I prefer the anti-join pattern.
Use "NOT EXISTS" along with INSTR
select *
from tablea a
where not exists(select 1 from tableb b where INSTR(a.name, b.nametag) > 0)
;
To exclude empty strings:
select *
from tablea a
where not exists(select 1 from tableb b where INSTR(a.name, b.nametag) > 0)
and length(a.name) > 0
;
I'm really confused here. Running the following query:
SELECT * FROM `articles` WHERE `form` = 'Depotplåster' AND `size` = 5
returns rows that also start with "5", despite me neither using LIKE nor a % wildcard operator. How come?
The size field is of type VARCHAR.
That is because you're using comparison between numeric and varchar data. MySQL will implicitly convert your column to double, resulting in 5. See this simple test data:
mysql> select * from test;
+-----------------+
| name |
+-----------------+
| 5 |
| 5 and some crap |
+-----------------+
2 rows in set (0.00 sec)
Now, "good" way: compare strings:
mysql> select * from test where name = '5';
+------+
| name |
+------+
| 5 |
+------+
1 row in set (0.00 sec)
And "bad" way: compare integers:
mysql> select * from test where name = 5;
+-----------------+
| name |
+-----------------+
| 5 |
| 5 and some crap |
+-----------------+
2 rows in set, 1 warning (0.05 sec)
-and here is your reason:
+---------+------+-----------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '5 and some crap' |
+---------+------+-----------------------------------------------------+
1 row in set (0.00 sec)
Finally, to understand, why is it so:
SELECT
CAST('5' AS DECIMAL) AS 5d,
CAST('5 and some crap' AS DECIMAL) AS 5sd,
CAST('5' AS DECIMAL) = CAST('5 and some crap' AS DECIMAL) AS areEqual;
Will result in:
+----+-----+----------+
| 5d | 5sd | areEqual |
+----+-----+----------+
| 5 | 5 | 1 |
+----+-----+----------+
1 row in set (0.00 sec)
-as you can see, non-significant part was just truncated (as mentioned in warning message above)
SELECT * FROM `articles` WHERE `form` = 'Depotplåster' AND `size` = '5'
-- this will compare the string 'size' with the string '5'
SELECT * FROM `articles` WHERE `form` = 'Depotplåster' AND `size` = 5
-- this will convert string 'size' to integer and then compare with the integer 5
The conversion of string to integer looks for ints i nthe beginning of the string, and takes the largest integer until the first non-numeric character.
select '5s4'=5, 's5'=5, '5'=5 -- =>1,0,1
SELECT *
FROM `articles`
WHERE `form` = 'Depotplåster'
AND `size` = '5'
You should quote 5 because MySQL convert string from the table to int without quotes.
I've searched for a question for hours and I haven't found an answer that was suitable for me, so... Here I come...
I'm Hungarian and we use the following accented characters in our language: áéíóöőúüű (and of course the capital counterparts)
I want to make a smart search in php where the user is allowed to enter a search word and it finds the result whether it has the accent or not and both in the MySQl table or the search field. So...
My MySQL table is using utf8_hungarian_ci
I can do the php conversion so that either the user types in 'Bla' or 'blá', it will return 'bla' and we are searching the mySQL database.
But my problem is... My database might have a 'bla fér' or a 'bláter' field entry. But if we search with 'bla' (from PHP) it only return 'bla fer'. How can I convert the field I'M searching to make 'bla fér'-> 'bla fer' and 'bláter' - > 'blater'. So essentially...
I want to get rid of the accented characters and make them into unaccented ones. But of course, only for the sake of searching. Please help! Thank you!
EDIT:
<?php
$search = $_GET["search"]; // May contain áéíóöőúüű
$accented= array("Ö","ö","Ü","ü","ű","Ó","ó","O","o","Ú","ú","Á","á","U","u","É","é","Í","í"," ","+","'","ő", "Ű", "Ő", "ä","Ä","ű","Ű","ő","Ő");
$nonaccented=array("O","o","U","u","u","O","o","O","o","U","u","A","a","U","u","E","e","I","i","_","_","_","o", "U", "O", "a","A","u","u","o","o");
$search = str_replace($accented,$nonaccented,$search);
$query = "SELECT id, name FROM people WHERE name LIKE '%$search%'"; // Database column 'name' may also contain áéíóöőúüű
?>
Here are some results from my tests. You can compare to yours:
CREATE TABLE `test` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(32) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
Table contents:
mysql> select * from test;
+----+---------+
| id | name |
+----+---------+
| 1 | bla |
| 2 | blater |
| 3 | bláter |
| 4 | bhei |
+----+---------+
4 rows in set (0.00 sec)
Search results;
mysql> select * from test where name like '%bla%';
+----+---------+
| id | name |
+----+---------+
| 1 | bla |
| 2 | blater |
| 3 | bláter |
+----+---------+
3 rows in set (0.00 sec)
Search with accent:
mysql> select * from test where name like '%blá%';;
+----+---------+
| id | name |
+----+---------+
| 3 | bláter |
+----+---------+
1 row in set (0.00 sec)
I get the same results even with COLLATE=utf8_hungarian_ci
For me, setting the character encoding to utf8_general_ci (or something else with "_ci") did the trick. The _ci means that SQL will match searches irrespective of case or accent.