• Aucun résultat trouvé

There are three types of logical operators: AND, OR, and NOT. You’ve seen ANDand OR in action. NOTis fairly intuitive when NULLisn’t involved. Here is an example that lists everyone not in department 10. The parentheses aren’t required, but as always they’re a nice touch. Frankly, it’s hard to overuse parentheses.

SELECT * FROM emp WHERE NOT (deptno=10);

The use of NOTin conjunction with NULL values is a bit nonintuitive. It’s important to remember that NOT always works in conjunction with a relationship comparison operator. If an operand in the subordinate expression is NULL, the expression will evaluate to NULL. The important thing to realize is that the inverse of NULL is NULL.

(This is different from true and false, which are inverses of each other.) So, when you apply NOTto a NULL condition, it will still be NULL. Here is an example:

SELECT * FROM emp WHERE NOT comm=500

Although there are many people without commissions, they aren’t listed in the results. For those people, the query evaluates as “select * from emp where NOT (NULL)”. On the other hand, the query for those people who have commissions that aren’t equal to 500 evaluates as “select from empwhere NOT(false)”. In the latter case, the whereclause evaluates to true because false is the inverse of true, whereas the for-mer statement evaluates to NULL, which is not true. If you want to get all the people who don’t have commissions of 500, you would do it as follows:

SELECT * FROM emp WHERE NOT (comm=500) OR (comm IS NULL)

The ANDand ORoperators have their own ways of dealing with NULL for the same reasons. If both operands are NULL, then the expression is NULL. Applying NOTto it won’t make it true. Cases where only one operand is NULL are more interesting. Con-sider the following two examples:

SELECT ename FROM emp WHERE (sal=2975 or comm=500) SELECT ename FROM emp WHERE (sal=2975 and comm=500)

In the database, Ward has a commission of 500, while Jones has a salary of 2,975. The first query returns both Ward and Jones, while the second query returns no rows.

This is completely expected behavior. Now, this is what happens when you apply NOT: SELECT ename FROM emp WHERE NOT (sal=2975 OR comm=500)

This returns only three rows—those who have commissions that aren’t 500 and that don’t have salaries that are 2,975. You know that commission either has a value or is NULL and that everyone has a salary. This means that the first operand of ORcan evalu-ate to either true or false, while the second operand can evaluevalu-ate to true, false, or NULL.

From this, you can deduce how the ORoperator behaves when it is confronted with an operand that has a NULL value. Since employees without commissions didn’t show up in our result here, you know the following:

■■ If one operand is NULL and the other TRUE, an ORexpression will evaluate to TRUE.

■■ If one operand is NULL and the other FALSE, an ORexpression will evaluate to NULL.

The second observation is the nonintuitive one. It seems that when you imply a NOT, you should get the inverse set—all the rows the query didn’t return without NOT. This isn’t the case, however. Instead, you only got the other employees who have commissions. For those employees, the original query evaluated to false; now it evaluates to true. For the other employees—those without commissions—the original query evaluated to NULL.

Since the inverse of NULL is NULL, those rows don’t show up when you apply NOT. Here’s the second case:

SELECT ename FROM emp WHERE NOT (sal=2975 and comm=500)

The original query returned no rows, so now you can expect to get all rows. But someone is missing—Jones! Jones is our employee with a salary of 2,975 and no com-mission. From this, you can deduce the following about ANDstatements:

154 Chapter 8

■■ When one operand is NULL and one is true, the expression will evaluate to NULL.

■■ When one operand is NULL and one false, the expression will evaluate to false.

This behavior may seem incredibly counterintuitive. The best way to think about it by considering the overall structure of the language. Consider the following two statements:

SELECT ename,comm,sal FROM emp WHERE NOT (5=5 AND comm=500) 5 always equals 5, so this statement is really just the following:

SELECT ename,comm,sal FROM emp WHERE NOT (comm=500)

As you’ve already learned, this statement should only display employees with com-missions that aren’t 500. If the preceding rules weren’t in place as they exist, these last two statements wouldn’t return the same result. Logically, they should. Putting a truism in a statement—or not having a truism—shouldn’t affect the end result.

By now, you’re probably thinking, “Isn’t there an easier way?” The treatment of NULLs has been debated ever since SQL started. The truth is that you have to distin-guish between NULL values and conditions that are false. If you just treat as false any condition in which a NULL is an operand, in your applications you’ll end up doing a lot of work sorting out what is NULL and what is false. In practice, the theory here is that you don’t generally want NULL conditions grouped in with false conditions. If the inverse theory were used—you do want NULL conditions grouped in with false conditions—we’d be talking about what steps are needed to keep them separate.

This discussion has been somewhat long-winded and theoretical. If your brain is hurting a bit, Table 8.12 should help. If in doubt, just look up how the expression is supposed to behave and remember the following rules of thumb:

■■ That NULL isn’t FALSE

■■ That the inverse of NULL isn’t TRUE

Table 8.12 lists the logical operators. The first and second operands are always inter-changeable for ANDand OR, while NOTonly has one operand.

Table 8.12 Logical Operators

OPERAND 1 OPERATOR OPERAND 2 EVALUATION

TRUE AND TRUE TRUE

FALSE AND TRUE FALSE

FALSE AND FALSE FALSE

TRUE AND NULL NULL

FALSE AND NULL FALSE

NULL AND NULL NULL

(continues)

Table 8.12 Logical Operators (Continued)

OPERAND 1 OPERATOR OPERAND 2 EVALUATION

TRUE OR TRUE TRUE

TRUE OR FALSE TRUE

FALSE OR FALSE FALSE

TRUE OR NULL TRUE

FALSE OR NULL NULL

NULL OR NULL NULL

NOT TRUE FALSE

NOT FALSE TRUE

NOT NULL NULL