MySql select on fields containing null values - mysql

In our company we moved our web application (LAMP) from one server (Ubuntu 10.04) to a new server (Ubuntu 12.04.2). Now we encountered a strange behavior I haven't seen before and I really do not know where to begin. Maybe someone can give me hint.
We have got the following simple table:
id data1 data2 data3
(int) (varchar) (int) (int)
-------------------------------------
1 (empty) 123 456
2 (null) 321 654
3 abc 555 666
(empty) means the field contains a empty string. (null) means that the field is null. Now we use the following very very simple query:
SELECT * FROM `table` WHERE `data1` != 'abc';
On our old server the query returned the lines with the ids 1 and 2 which, I guess, is absolutely correct since !='abc' matches those two recordsets.
On our new server the query only returns the recordset with the id 1. Recordsets containing null in the select fields are suddenly ignored by the query somehow.
Just to make it more clear: I know that IS NULL could be used, but that would result in checking all queries and tables in the application matching this situation.
Now the questions are:
Did we had luck on our old server that the query behaved as expected by returning lines 1 and 2 or does the new server behave correct by returning only line 1?
Generally: Should !='abc' match the recordsets 1 and 2 or should it only match id 1?
Is it possible that there is a setting in the mysql configuration that controlls that behaviour? I am a little stuck with that. Every help is appreciated!
Thanks in advance...

Because null is a special case, if you want null values to be included, you should explicitly specify that you want them.
SELECT * FROM table WHERE (data1 <> 'abc' or data1 is null)
The expected server behavior, is ignore nulls unless you ask for them...

SELECT * FROM `table` WHERE `data1` = '';

Related

MYSQL: Can't get simple SQL statement to execute correctly

So I have been using many SQL statements however for the life of me, I can't get this one to work.
I have a table called tb_iptable, it has two fields uId which is an INT and 'ipAddress which is varchar.
The table holds the following data
uId | ipAddress
------------------
2 | 76.76.76.76
|
|
however when is use the SQL
"SELECT * FROM tb_iptable WHERE uId='2' and ipAddress='76.76.76.76'"
but also
"SELECT * FROM tb_iptable WHERE ipAddress='76.76.76.76'"
it returns zero results.
I have no idea why this does not work, however, I may just be being stupid.
use id=2 insted of id = '2'
simply don't use( ' ) around integer Id

Count returns 0 for a column that exists

So i have a MySQL table that contains 2 fields - deviceID and jobID. Below is a sample of what the table looks like with Data in it:
+----------------------+----------------------+
| deviceID | jobID |
+----------------------+----------------------+
| f18204efba03a874bb9f | be83dec5d120c42a6b94 |
| 49ed54279fb983317051 | be83dec5d120c42a6b94 |
+----------------------+----------------------+
Usually i run a query that looks a little like this:
SELECT Count(deviceID)
FROM pendingCollect
WHERE jobID=%s AND deviceID=%s
Now this runs fine and usually returns a 0 if the device doesnt exist with the specified job, and 1 if it does - which is perfectly fine. HOWEVER, for some reason - im having problems with thew second row. The query:
SELECT Count(deviceID)
FROM pendingCollect
WHERE jobID='be83dec5d120c42a6b94' AND deviceID='49ed54279fb983317051'
is returning 0 for some reason - Even though the data exists in the table3 and the count should be returned as 1, it is returning as 0... Any ideas why this is?
thanks in Advance
EDIT:
Sorry for the type guys! The example SQL query shouldnt have had the same devID and jobID.. My Mistake
EDIT 2:
Some people are suggesting i use the SQL LIKE operator.... Is there a need for this? Again, when i run the following query, everything runs fine and returns 1. It only seems to be on the deviceID "49ed54279fb983317051" that is returning the error...
SELECT Count(deviceID)
FROM pendingCollect
WHERE jobID='be83dec5d120c42a6b94' AND deviceID='f18204efba03a874bb9f'
The above query works as expected returning 1
You need to provide the correct value for jobID. Presently you are providing the value of deviceID in jobID which is not matching and hence returing 0 rows.
SELECT Count(deviceID) FROM pendingCollect
WHERE jobID='49ed54279fb983317051' AND deviceID='49ed54279fb983317051'
^^^^^^^^^^^^^^^^^^^^^^^
The reason why
jobID=%s and deviceID=%s
which I think you mean
jobID like '%s' and deviceID like '%s'
was working because both were matching. But now since you are using the AND condition and providing jobID value same for both so it would not match any row. And will return 0 rows.
EDIT:
You query seems to be correct and is giving giving the correct result.
SQL FIDDLE DEMO
You need to check if there is any space which is getting added to the values for the jobID and deviceID column.
This is because of the AND operator. AND means both conditions must be true. Instead of AND, use OR operator.
SELECT Count(deviceID)
FROM pendingCollect
WHERE jobID = '49ed54279fb983317051' OR deviceID = '49ed54279fb983317051'
Check the real value the column contains, there might be some unprintable character in it:
SELECT deviceID, hex(deviceID), hex('49ed54279fb983317051')
FROM pendingCollect
WHERE jobID='be83dec5d120c42a6b94';
If there is anything weird in that deviceID, it should show as a difference in the hex output - for the value you want, I did not add it to the where condition as you have problems "targeting" it, so this query will return rows even for the other devices with the same jobID.

UNION of empty set with AVG function and any non-empty set

this is my first question ever, so please be patient.. :)
We are two developers and both have the same MySql DB with same tables and values.
One is MySql version 5.5 and works ok (apparently) as I am told by the other developer.
On my machine with MySql 5.1.44 (a basic MAMP install) I have the following weird problem.
A very huge query (not mine) fails with error "Column 'xd' cannot be null".
Removing pieces I slimmedi it down to this:
select xd, avg(media) from questionario_punteggi where somefield = 1 union select 1,2
Note, there is no record with somefield = 1 so the first select returns an empty set
We have a SELECT with AVG() function that returns an empty set UNION another SELECT that returns something (1,2 are just random values I put now as an example)
If I remove the AVG() the query works.
If I remove xd (and the 2 of 1,2 to the right) the query works.
If I remove the UNION the query works.
If I set some record with somefield = 1 the query works.
On the other machine 5.5 the query works.
Otherwise the error is:
1048 - Column 'xd' cannot be null
Fields are:
`xd` char(3) NOT NULL DEFAULT '001',
`media` decimal(7,4) NOT NULL DEFAULT '0.0000',
`somefield` tinyint(4) NOT NULL DEFAULT '0',
Gosh. Any help? Thanks.
UPDATE
It has been reported to me as a BUG in MySql <= 5.1 that was fixed before MySql 5.5. I don't have the details but I trust the source
I suggest reversing the order of the queries in the UNION.
This is because the first SELECT in a UNION determines the data type of the columns in the resultset; in your case, the first column of the UNION took the type of the questionario_punteggi.xd column: that is, CHAR(3) NOT NULL.
Since you are applying an aggregate function over the first part of the UNION, it results in a single row even though no records are matched by the filter criterion. As documented under GROUP BY (Aggregate) Functions:
AVG() returns NULL if there were no matching rows.
The value taken for the hidden xd column would normally be an indeterminately chosen record from those that match the filter (which is why you probably don't want to do that anyway); however, since in this case no records match, the server instead returns NULL (which obviously cannot go into a column with the NOT NULL attribute).
By reversing the order of the UNION, the column will not have the NOT NULL attribute. You may need to alias your columns appropriately:
SELECT 1 AS xd, 2 AS avg_media
UNION
SELECT xd, AVG(media) FROM questionario_punteggi WHERE somefield = 1
Using this to explain each of your observations in turn:
If I remove the AVG() the query works.
Since aggregation is no longer performed, the first SELECT in the UNION yields an empty recordset and therefore no NULL record in the first column.
If I remove xd (and the 2 of 1,2 to the right) the query works.
Since the hidden column is no longer selected, MySQL no longer returns NULL in its place.
If I remove the UNION the query works.
This is the bug that was likely fixed between your version of MySQL and your colleague's: the NOT NULL attribute shouldn't really apply to the UNION result.
If I set some record with somefield = 1 the query works.
The value selected for the hidden column is an indeterminate (but non-NULL value, due to the column's attributes) from the matching records.
On the other machine 5.5 the query works.
This bug (I'm still searching for it) must have been fixed between your respective versions of MySQL.
try using the SELECT IFNULL();
Select IFNULL(xd,0), avg(media) f
rom questionario_punteggi
where somefield = 1
union
select 1,2
http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_ifnull

mysql query string field with int, returns equivalent of ('int-%')

This is kind of a weird quirk I noticed and I really just wanted to see if someone could provide insight as to why its happening.
Lets say we have a field called "account" that's a varchar(x)
These two queries will return the same result set.
SELECT * FROM table WHERE account = 1234;
SELECT * FROM table WHERE account LIKE '1234%';
I stumbled on this by accident in a script I wrote to migrate some older data and I accidentally forgot to encapsulate my string.
Can anyone tell me why this behavior happens?
update:
I feel like I may have no explained this well enough so I'm going to provide a sample table:
table_name:
id - INT
account - varChar(50)
entries:
ID - account
1 - "1"
2 - "12"
3 - "123"
4 - "1234"
so:
1:
SELECT * FROM table_name WHERE account LIKE '1%'
will return entries 1, 2, 3, 4
2:
SELECT * FROM table_name WHERE account = 1
will return entries 1, 2, 3, 4
3:
SELECT * FROM table_name WHERE account = '1'
will return entry 1
Why is 1 the same as 2, and why is 2 not the same as 3
http://dev.mysql.com/doc/refman/5.0/en/type-conversion.html
"...MySQL automatically converts numbers to strings as necessary, and vice versa."
This is because % is a meta character which means any number of characters including zero characters. Like keyword looks for the pattern which begins with 1234.
Since account = 1234 which also matches the criteria, you get the same result.
I think at this point this has been discovered as a MYSQL bug, I filed a bug report id #67427 if anyone is interested in getting an update I would direct you to view it through http://bugs.mysql.com/

mySql new rows can only be searched with LIKE, has anyone had this before?

A bit of background
I'm running mySQL on a mac
I have a few databases setup that have been working okay
I have recently created a new table from a sqlDump from another server.
I am having an issue with new rows that equal = a value that I know exists
e.g. Table setup
id=1 name='dave' - already exists in database
id=2 name='john' - I add a new row
Following are the sql I tried with results...
Select * from tablename where id=1 -- I get the correct Dave result.
Select * from tablename where `name` = 'dave' -- I get the correct Dave result.
Select * from tablename where id=2 -- I get the correct John result.
Select * from tablename where `name` like 'joh%' -- I get the correct John result.
Select * from tablename where `name` = 'john' -- (No result!) eek!
Anyone seen this before? it's in the database but a direct match on the name field is not yielding a result.
Thanks in advance
M
One possibility: there could be a trailing space after 'john' in the name column.
One way to check that:
select `name`,char_length(`name`), char_length('john')
from tablename
where id = 2
An easy way to not have to deal with that problem would be to trim your input (if you don't expect to ever have preceding or trailing white space.
In that case you could have a query like:
Select * from tablename where trim(`name`) = trim('john')
I agree with the comments on your question, that it is most likely a hidden space or something similar. If you include the column definitions so we can check the data that your using with the types we could help more. Remove the entry and and retry with a different name other than john and see if you can replicate the problem.