How can I test an IF statement in MySQL ?
I need to know, what happens when a query is into a IF statement and it returns nothing (0 row selected) ?
In other word, what a SELECT query returns when the no row is selected? Will it return NULL? If yes, so will this throw an error? IF ( NULL ) THEN ...? Or in this case just the statement of that IF won't execute?
In reality, I have a code like this:
IF ( SELECT banned FROM users WHERE id=new.user_id ) THEN
// do stuff
Note: banned column contains either 0 or 1.
All I want to know, is my code safe when that query doesn't return any row? I mean will it throw an error or nothing happens (just that IF statement doesn't execute) ?
Noted that I wanted to test it myselft, but I don't know how can I test a IF statement in MySQL. For example, I wanted to test it by this code:
BEGIN
IF ( SELECT banned FROM users WHERE id=new.user_id ) THEN
SELECT 'test';
ENDIF;
END
But code above doesn't even run. That's why I've asked this question.
An IF statement can be tested in the context of a MySQL stored program (a procedure, function or trigger.) MySQL doesn't support anonymous blocks.
To test an IF statement, you can create a procedure
DELIMITER $$
CREATE PROCEDURE foo
BEGIN
IF ( some_condition ) THEN
SELECT 'evaluation of some_condition returned TRUE' AS msg;
ELSE
SELECT 'evaluation of some_condition did NOT return TRUE' AS msg;
END IF;
END$$
DELIMITER ;
CALL foo;
I need to know, what happens when a query is into a IF statement and it returns nothing (0 row selected) ?
What you're actually asking about here is a scalar subquery.
Scalar subqueries return exactly one column and exactly one or zero rows. Returning NULL and matching zero rows are equivalent, and neither will throw an error. In both cases, the subquery's return "value" is NULL.
You will, however, throw an error if you manage to write a scalar subquery that returns more than one row (such as when you forget WHERE in the subquery. But zero rows is perfecty valid.
IF tests for truthiness, and anything that IS TRUE ... which technically means any expression that both IS NOT FALSE and IS NOT NULL -- satisfies the IF. If the return value is FALSE (0) or NULL then the ELSE branch will be followed, if present.
I highlighted keyword phrases like IS NOT FALSE, above, to emphasize the point that these are logical operators in SQL.
Try queries like SELECT 0 IS FALSE (returns 1, because it is) or SELECT NULL IS NOT TRUE (returns 1, because it isn't) or SELECT NULL IS NOT FALSE (also returns 1, because it isn't) SELECT NULL IS FALSE (returns 0, because it isn't) to see what I mean.
Related
I have the following case statement, the AppointmentDate isn’t always populated and therefore require to pull from other date fields - looking to have one appointment date (populated from many fields)
When running this statement, doesn’t return full results.
,Case=Appointment
When AppointmentDate Is Null Then ChaseDate
When ChaseDate Is Null Then DueDate
Else AppointmentDate
End
Any thoughts on where I’ve went wrong?
Thanking you in advance.
You haven't stated if this is supposed to be an expression in SSRS or this is part of your dataset query.
Assuming SQL Server here...
If this is part of your dataset query then you can do something like
SELECT
FieldA, FieldB,
myAppointmentDate = COALESCE(AppointmentDate, ChaseDate, DueDate)
FROM myTable
COALESCE will return the first non-null value
If you are trying to do this in an SSRS expression then you need to use the SWITCH() statement.
=SWITCH(
Fields!AppointmentDate.Value <> Nothing, Fields!AppointmentDate.Value,
Fields!ChaseDate.Value <> Nothing, Fields!ChaseDate.Value,
Fields!DueDate.Value <> Nothing, Fields!DueDate.Value,
True, Fields!AppointmentDate.Value
)
This will return the first expression that is true, if non of the first three exression return true, the final True acts like an else (which in your case would return Nothing anyway)
I need a condition that when used with an IN condition, it won't return any results. I initially thought this would work, but it still gives back results:
SELECT * FROM MyTable WHERE myColumn IN (SELECT FALSE FROM dual WHERE FALSE);
Is there a condition I could put in the IN condition to have it always return no results?
NOTE: This is being used in a PHP function where the column could be any type with any value.
Instead of false use null. When null occurs in an expression, that always leads to a overall null value (there are some exceptions, like with is null but not in this context of in):
... in (select null from dual where null)
I need to query data from a second table, but only if a rare set of conditions in the primary table is met:
SELECT ..., IF(a AND b AND c AND (SELECT 1 FROM tableb ...)) FROM tablea ...
a, b, and c conditions are almost always false, so my thinking is the subquery will never execute for most rows in the result set and thus be way faster than a join. But that would only true if the IF() statement short circuits.
Does it?
Thanks for any help you guys can provide.
The answer is YES.
The IF(cond,expr_true,expr_false) within a mysql query is short-circuited.
Here a test, using #variables to prove the fact:
SET #var:=5;
SELECT IF(1 = 0, (#var:=#var + 1), #var ); -- using ':=' operator to modify 'true' expr #var
SELECT IF(1 = 1, #var, (#var:=#var + 1) ); -- using ':=' operator to modify 'false' expr #var
SELECT #var;
The result is '5' from all three SELECT queries.
Had the IF() function NOT short circuited, the result would be a '5' from SELECT #1, and '6' from SELECT #2, and a '7' from the last "select #var".
This is because the 'true' expression is NEVER executed, in select #1 and nor is the false expression executed for select #2.
Note the ':=' operator is used to modify an #var, within an SQL query (select,from, and where clauses). You can get some really fancy/complex SQL from this. I've used #vars to apply 'procedural' logic within a SQL query.
-- J Jorgenson --
With J. Jorgenson's help I came up with my own test case. His example does not try to short circuit in the condition evaluation, but using his idea I came up with my own test and verified that MySQL does indeed short-circuit the IF() condition check.
SET #var:=5;
SELECT IF(1 = 0 AND (#var:=10), 123, #var); #Expected output: 5
SELECT IF(1 = 1 AND (#var:=10), #var, 123); #Expected output: 10
On the second example, MySQL is properly short-circuiting: #var never gets set to 10.
Thanks for the help J. Jorgenson!
It depends.
IF doesn't short-circuit such that it can be used to avoid truncation warnings with GROUP_CONCAT, for example in:
set ##group_concat_max_len = 5;
select if(true or #var:=group_concat('warns if evaluated'), 'actual result', #var);
the result will be 'actual result' but you'll get a warning:
Warning (Code 1260): Row 1 was cut by GROUP_CONCAT()
which is the same warning you get with less trivial GROUP_CONCAT expressions, such as distinct keys, and without the IF at all.
Try it in the SQL analyzer. If you want to be on the safe side and not have to trust the database to work one way (and not to change that behavior ever in new versions), just make two queries and do the IF programmatically.
Currently I have this statement
IF(0.5 < SELECT (FLOOR(10*RAND()*pResourcium) AS TestVar FROM siegeverse.rooms rm) AS T))
THEN SELECT 'TEST'
Any idea why it is failing? Trying to get it to output test for each row if the selected element is greater than 0.5
Thanks!
SELECT statement in such scalar comparison contexts should return only one row. In your case, it might be returning multiple rows and so is failing. The following rewritten query is close to what you are interested in:
IF EXISTS (SELECT *
FROM
(SELECT
CASE
WHEN (FLOOR(10*RAND()*pResourcium) >= 0.5 THEN 'TEST'
ELSE NULL
END AS TestVar
FROM
siegeverse.rooms rm
) AS A
WHERE A.TestVar IS NOT NULL)
THEN
<run the stored procedure>
Can anyone help me understand or post any ideas concerning this where clause?
sql was here
I've changed the table name, but other than that, any idea what the developer was trying to do here?
There is nothing else after that, that's the where clause.
If (table.date_field = (select max(table2.exit_date) from table as table2)) is null the it'll return 1=1, which basically means there's no where clause at all.
Now let's look into that nasty expression. I can only assume that if "a = b" is not true then that's also equivalent to null, otherwise it seems like the first branch would always happen. It looks like it's trying to say "if the latest exit date is equal to the date field, select those, otherwise have no where clause". However, I don't think that this will work at all. It really looks like either way, each row will be selected.
The MySQL ifnull function returns the first argument if it is not null, otherwise the second argument. This looks like it tries to compare table.date_field to the max(table2.exit_date), and return true if the comarison was not possible due to nulls.
It looks to me like he is trying to find the row where table.date_field is equal to the maximum of table.exit_data. There is a check for null which I think would happen in any of these cases:
table is empty
all rows in table have exit_data set to NULL
table.date_field is NULL for the row in question
In any of these three cases, the row will be returned. I don't understand why he uses the string '1=1' instead of, to give some examples: 1=1, 1 or true, but it appears to work fine. In the first case I assume that there will be no rows in the result set anyway (depending on the rest of the query) so he was probably trying to handle one of the other two cases - I'd guess the last one.
This is only an explanation of what is happening. To understand why he is doing this, it would help if you gave a little more context.
MySQL is nonstandard in that true is really equal to the numeric value 1. Any expression that evaluates to true, or any nonzero value, satisfies the condition.
mysql> CREATE TABLE foo AS SELECT 1=1 AS f;
mysql> SHOW CREATE TABLE foo;
CREATE TABLE `foo` (
`f` INT NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
So the following WHERE clause is legal in MySQL, but not in most other SQL databases:
... WHERE 1;
Some people use 1=1 as a placeholder condition meaning true, but putting it in a string is meaningless because SQL expressions have no equivalent to an eval() function as other languages have. In this case, the leading character 1 in the string is implicitly cast to a numeric value 1, which is interpreted as true in MySQL. So it probably works as intended, but kind of by accident.
The use of IFNULL() is so that if either date_field or MAX(exit_date) is NULL, it returns the row. If you didn't use this function, then anything = NULL would evaluate as unknown, which means the row would not be returned.
It says basically if table.date_field = max exit date or if max exit_date is null or table.date_field is null return true. Will return false if max exit_date is not null and table.date_field is not null but they do not equal.