Mysql test against value excludes NULL entries - can someone explain? - mysql

I've got a table shop_categories with a field called category_is_hidden which is defined as:
category_is_hidden tinyint(4) DEFAULT NULL
In the database, the values for that field are either 1 or NULL.
SELECT * FROM shop_categories where category_is_hidden IS NULL
returns all the null entries.
SELECT * FROM shop_categories where category_is_hidden <> 1
returns an empty sets (that is, it excludes the null values).
Why does that last statement not include null entries? isn't null <> 1?
Edit: Tested on MySQL 5.1 & 5.5

Since your category_is_hidden column appears to be a flag, I'd change it to tinyint(1) and make it be either 1 or 0 instead of 1 or NULL. Allowing a column to be null will add a byte to the storage requirements of the column, leading to an increased index size.
Next, the question you actually asked. NULL by definition is UNKNOWN. Your query says "give me everything where category_is_hidden is not 1". But the NULL column values are all unknown. So MySQL doesn't know if they are not 1. You need to rewrite the WHERE as IS NOT NULL. If your column is going to be tri-state (1, NULL, other value), you need to make your WHERE have an OR in it to allow for that.

If a field is null, then it means that it does not have a value. It is not zero, or an empty string. If you check if NULL <> 1, then it is not, because it is not a number; it is not anything, and therefore cannot be compared.

Related

Why is a row with a value NULL still choosen when there is a value of 1 in the column [duplicate]

This question already has answers here:
MySQL comparison with null value
(7 answers)
Closed 3 years ago.
I have a MySQL table which has a column in which some rows have the value 1. This is because i want use a query like "where column !='1' " to select all rows which do not have a 1 (the character 1) in this column/field.
Strangely, when i query the table like:
select * from table where column !='1'
all the rows where there is NULL in this same column are also treated as if there would be a 1 (character 1) in the column.
According to my DB knowledge the character 1 and NULL are definitely not the same and should not be treated the same in a query!?
I know today PDO is recommended but this is not a internet accessible web application but just a local db in which i sort some quite unimportant data. Once when i have time i will rewrite it with PDO but not at the moment.
Thanks for any help
Markus
Just add a IS NULL to your query.
select * from table WHERE column <> '1' OR column IS NULL
When the column's value is NULL then the condition is:
WHERE NULL !='1'
and since any comparison to NULL has as result the value NULL then the condition is:
WHERE NULL
which clearly is not
WHERE TRUE
so that row is not returned.
What you can do if you want NULLs in the results is to explicitly include the condition in the WHERE clause:
WHERE column !=' '1' OR column IS NULL

INNODB -> Should the default column be zero or null?

My english is a little weak sorry
When using INNODB, must the column be 0 or should it be null?
Does the problem occur if the joined columns are defined as 0?
Finally, which is better in terms of performance?
Thanks.
Ignore the problem. You do not have to provide a DEFAULT value. You do not have to declare a column NULL (or NOT NULL).
Instead...
Think about the application.
Case 1: Your application will always have a value for that column, and it will always specify the value. Then declaring the column to be NOT NULL and not providing a DEFAULT makes sense.
Case 2: You don't have a value yet. Example: The table has start_date and end_date. You create a row when the thing "starts", so you fill in start_date (see Case 1) but leave end_date empty. "Empty" could be encoded as NULL and DEFAULT NULL. Later you UPDATE the table to fill in the end_date with a real value.
Case 3: The table has a "counter". When you initially add a row, the counter needs to start with "1". Later you will UPDATE ... SET counter=counter+1. You could either explicitly put the "1" in when you create the row, or you could leave out the value when inserting, but have the column declared NOT NULL DEFAULT '1'
NULL could represent "not-yet-filled-in" (Case 1), "don't know the value", "use the default", and several other things. This is an application choice.
There are other uses for NULL. Unless you have a use for NULL, declare each column NOT NULL.
If, when INSERTing, you specify all the columns, then there is no need for DEFAULTs. DEFAULTs are a convenience, not a necessity. Without a DEFAULT, you get "0" for numeric NOT NULL columns, or '' for strings.
Performance -- Probably not an issue. Do you have a particular example we should discuss?
JOINing -- I would avoid joining on a column that might have NULL in it. This rarely happens in "real life", since one joins on the unique identifier for rows in one column with a column in the other table:
FROM A JOIN B ON B.id = A.b_id
That is, B.id is probably the PRIMARY KEY of B, hence cannot be NULL. On the other hand, A.b_id could be NULL to indicate there is no row in B corresponding to the row in A. No problem.

how to count values in a row that default instance have NONE?

Explain :
I have a table for Users and there is a column android_token, that can be null, but DEFAULT has NONE, means by default it doesn't sent null value for each row.
Now..
When I want to select all users that have their android_token not null, I can't get the result..
for example
SELECT * from tbl_users where android_token IS NOT NULL;
it gives me no sorting result, because rows that have it's android_token value are ok, but other users that have their android_token empty don't have even NULL value on it, in the structure of the table android_token DEFAULT IS NONE.
Can someone explain me, how can I update the table and send NULL value for each row that IS EMPTY only , or how can I sort users that have android_token with current configuration?
Thanks in Advance.
Explanation
Implicit defaults are defined as follows:
For numeric types, the default is 0, with the exception that for
integer or floating-point types declared with the AUTO_INCREMENT
attribute, the default is the next value in the sequence.
For date and time types other than TIMESTAMP, the default is the
appropriate “zero” value for the type. For the first TIMESTAMP column
in a table, the default value is the current date and time. See
Section 10.3, “Date and Time Types”.
For string types other than ENUM, the default value is the empty
string. For ENUM, the default is the first enumeration value.
Code
If android_token is a string:
UPDATE tbl_users SET android_token=NULL WHERE android_token='';
This will change all empty cells to NULL

mysql company update date value is blank

I have a table company_update and have the following field:
ID auto_increment
company_status varchar(20)
company_update_date date
For company_update_date field, if the value is blank, should I use NULL or '0000-00-00'? Which one is better?
NULL means "The data does not exist, or is unknown." Date('0000-00-00') essentially means, "This happened before time began." It's up to you, but I'd probably go with NULL.
NULL is is better because we can easily compare null value to other value
But if column has been defined with NOT NULL or with a default
'0000-00-00'. You need to change the column definition to allow NULLs and have no default.
The Null is better to know as start point. Example : You create company but it still not active (Now you set Null) you decided will be active after one month will you insert the date. So, you can check the Active, Pending, till not active. As other colleague say depending on requirement.

Mysql: where ..id != X doesn't include the NULL foreign key

I have this Mysql table:
assignment: assignment_id (PK), company_id (FK), ...some other fields...
The FK company_id can be NULL if an assignment is not yet assigned to a company.
Now, I want to query all assignments that are not for company with id 2. So I did:
SELECT * FROM assignment WHERE company_id != 2
To my surprise, assignments with company_id NULL aren't returned in the results. I'd say that NULL != 2 so it should be returned. It works fine if I go with
(company_id IS NULL OR company_id != 2)
Can someone explain me the logic behind this? Does it have to do with the FK constraint?
The logic is simple: you can't really say whether or not NULL is equal to 2, because you don't know anything about NULL. Quoting the doc:
Conceptually, NULL means “a missing unknown value” and it is treated
somewhat differently from other values. You cannot use arithmetic
comparison operators such as =, <, or <> to test for NULL. [...]
Because the result of any arithmetic comparison with NULL is also
NULL, you cannot obtain any meaningful results from such comparisons.
You've already shown one possible workaround in your question, the other one is using <=> (NULL-safe comparison operator):
SELECT * FROM assignment
WHERE NOT(company_id <=> 2)
NULL is not a number. It is a completely different thing in mysql. So you can not compare something to NULL. To clear your confusion, in your case, all the fields where FK is not 2 are those fields where the "value" is other than 2. But when the value is NULL, it means there is no value assigned at all.
See MySql documentation