I was wondering why MYSQL uses a single equals sign in conditional statements instead of the more typical two equals signs. Is there a technical/historical reason for this? Thanks.
Hi, I was wondering why MYSQL uses a single equals sign in conditional statements instead of the more typical two equals signs. Is there a technical/historical reason for this? Thanks.
Comparison is much more common in SQL than assignment.
That's why SQL uses more short syntax to do more common things.
In classical SQL, comparison can be distinguished from assignment by context (assignment can be only in SET clause of an UPDATE statement), that's why one operator can be used for both operations.
In MySQL's extension to SQL, assignment to a session variable is denoted by :=
More like historical.
It's SQL. It has used a single equals sign for comparison since the early '70s.
There is never a case for ambiguity in SQL.
In the original A Guide to the SQL Standard by C.J.Date (1987 edition), = for assignment is only used in the SET clause of UPDATE. Everywhere else = is used it is used for comparison.
But in other languages, such as C/C++/C#/Java, = can be used as assignment but it also returns a value. So a = b means "set a equal to b, and return a" whereas a == b means "return true if a and b are equal". (This leads to a very common bug in C programs, because if (a = b) and if (a == b) are both valid, since the result doesn't have to be a bool.)
Some languages like JavaScript/ECMAScript also introduce === as a third type of comparison. In those languages, == means "convert to same type and compare" whereas === means "return true only if they are the same type and same value."
Related
I have an issue with this simple query :
#Query("SELECT c FROM Cat c WHERE c.id IN (:idCat) OR :idCat IS NULL")
List<Cat> getAllCatWithOrWithoutId(#Param("idCat")List<String> idCat);
Which queried in a list, or, if the id is not mentionned, select all cats in table (idCat is optional actually).
It seems working when it's an "=" operator instead of IN but when I run the query I have the error message is : "invalid relational operator".
Even if I try with a native query.
I tried to replace idCat value by single value (it worked), or by null (it worked too), but not when I put several values.
Is it something wrong in syntax or is it simply impossible with an IN statement?
When you provide a filled list, your second part of the query (OR :idCat IS NULL) is translated to a list of values to compare to "IS NULL".
As stated on JSR-338, chapter 4.6.11, "[a] null comparison expression tests whether or not the single-valued path expression or input parameter is a NULL value", so it is not expected to support a filled list as an argument. To check lists, there is the "IS [NOT] EMPTY" expression, but it expects a collection_valued_path_expression and it is not your case.
I've stumbled sometimes with strange behavior of some persistence providers where they supported (anti-spec) this kind of comparison if you surround the parameter with parenthesis, but, again, you can not rely on it for future evolutions.
The best approach in your case would be define two different JPQLs or methods to deal with your both desired scenarios.
I want to express the condition (in a where clause) where a value in one column mandates a condition must be met in another column. This is a logical implies (→) relation and is equivalent to "not A or B" (¬A∨B).
Is there an existing SQL operator or function for that? I fear the (not(A) or B) expression may confuse future maintainers of my code who do not have a CS background.
No such operator. Define such a function or use comments.
I would like to know if there are any differences in between the two not equal operators <> and != in Oracle.
Are there cases where they can give different results or different performance?
No there is no difference at all in functionality.
(The same is true for all other DBMS - most of them support both styles):
Here is the current SQL reference: https://docs.oracle.com/database/121/SQLRF/conditions002.htm#CJAGAABC
The SQL standard only defines a single operator for "not equals" and that is <>
Actually, there are four forms of this operator:
<>
!=
^=
and even
¬= -- worked on some obscure platforms in the dark ages
which are the same, but treated differently when a verbatim match is required (stored outlines or cached queries).
At university we were taught 'best practice' was to use != when working for employers, though all the operators above have the same functionality.
According to this article, != performs faster
http://www.dba-oracle.com/t_not_equal_operator.htm
I am building some prepared statements that use parametrized values. As an example:
SELECT * FROM "Foo" WHERE "Bar"=#param
Sometimes #param might be NULL. In such cases, I want the query to return records where Bar is NULL, but the above query will not do that. I have learned that I can use the IS operator for this. In other words:
SELECT * FROM "Foo" WHERE "Bar" IS #param
Aside from the differing treatment of NULL, are there any other ways in which the above two statements will behave differently? What if #param is not NULL, but is instead, let's say, 5? Is using the IS operator in that case a safe (and sane) thing to do? Is there some other approach I should be taking?
You want records from Foo where Bar = #param, or if #param is null, where Bar is null. Some of the proposed solutions will give you null records with nonnull #param, which does not sound like your requirement.
Select * from Foo where (#param is null and Bar is null) or (Bar = #param)
This doesn't say whether this is Oracle or SQL Server or another RDBMS, because they each implement slightly different helper functions. SQL's ISNULL(first, second) like NVL(first, second). I like SQL Server's COALESCE() for the general applicability.
The IS comparison is only for null comparisons.
If you are using SQL Server and if you really need a different 3VL logic truth table to solve your problem (that is, if you have a specific need for "NULL=NULL" to be "true" at some point in time, and also recognize that this is deprecated and barring your reasons, not a good idea in general), within your code block you can use the directive
SET ANSI_NULLS OFF
Here's the BOL on it:
http://msdn.microsoft.com/en-us/library/ms188048.aspx
You may be thinking about this incorrectly. If you're talking about SQL Server, for example (since that's what I have to hand), your second example will result in a syntax error. The value on the right-hand side of IS cannot be 5.
To explain, consider MSDN's explanation of these two operators in T-SQL (note that asking about "SQL" and about "SQL Server" are not necessarily the same).
Equals (=) operator
IS NULL operator
Notice something important, there. There is no such thing as the "IS" operator in T-SQL. There is specifically the <expression> IS [NOT] NULL operator, which compares a single expression to NULL.
That's not the same thing as the = operator, which compares two expressions to each other, and has certain behavior when one or both of the expressions happens to be NULL!
Edit:
(Update from OP: This doesn't do what I If #param is 5, then I want to see only records where Bar is 5. I want to see records where Bar is NULL if, and only if, #param is NULL. I apologize if my question didn't make that clear.)
In that case, I think you should try something like this:
SELECT * FROM Foo WHERE Bar=#param OR (Bar IS NULL AND #param IS NULL)
Previous post:
Why not simply use OR ?
SELECT * FROM "Foo" WHERE "Bar"=#param OR "Bar" IS NULL
In SQL Server, you can use ISNULL:
SELECT * FROM "Foo" WHERE ISNULL("Bar",#param)=#param
I don't know what version of SQL you are using but IS makes no sense in the context you just described. I get a syntax error if I try to use it the way you described. Why would you want to use it over = anyway? This is the common usage and the one software maintainers woudl expect to find.
What specific database are you using?
If you're doing searches based on null (or not null), using IS is the way to go. I cannot provide a technical reason but I use this syntax all the time.
SELECT * FROM Table WHERE Field IS NULL
SELECT * FROM Table WHERE Field IS NOT NULL
I want to be able to pass something into an SQL query to determine if I want to select only the ones where a certain column is null. If I was just building a query string instead of using bound variables, I'd do something like:
if ($search_undeleted_only)
{
$sqlString .= " AND deleted_on IS NULL";
}
but I want to use bound queries. Would this be the best way?
my $stmt = $dbh->prepare(...
"AND (? = 0 OR deleted_on IS NULL) ");
$stmt->execute($search_undeleted_only);
Yes; a related trick is if you have X potential filters, some of them optional, is to have the template say " AND ( ?=-1 OR some_field = ? ) ", and create a special function that wraps the execute call and binds all the second ?s. (in this case, -1 is a special value meaning 'ignore this filter').
Update from Paul Tomblin: I edited the answer to include a suggestion from the comments.
So you're relying on short-circuiting semantics of boolean expressions to invoke your IS NULL condition? That seems to work.
One interesting point is that a constant expression like 1 = 0 that did not have parameters should be factored out by the query optimizer. In this case, since the optimizer doesn't know if the expression is a constant true or false until execute time, that means it can't factor it out. It must evaluate the expression for every row.
So one can assume this add a minor cost to the query, relative to what it would cost if you had used a non-parameterized constant expression.
Then combining with OR with the IS NULL expression may also have implications for the optimizer. It might decide it can't benefit from an index on deleted_on, whereas in a simpler expression it would have. This depends on the RDBMS implementation you're using, and the distribution of values in your database.
I think that's a reasonable approach. It follows the normal filter pattern nicely and should give good performance.