这个sql语句有什么问题?

时间:2011-07-24 00:04:06

标签: sql oracle11g

我写的这句话在所有情况下都能正常工作,除了一个案例

SELECT p.priv_no FROM osqs_privileges p,osqs_users_privileges up 
WHERE up.priv_no = p.priv_no AND up.user_no = 54 AND up."GRANT" = 'Y' 
    UNION 
SELECT p.priv_no FROM 
osqs_privileges p,osqs_groups_privileges gp,osqs_users_groups ug,osqs_users_privileges up 
    WHERE gp.priv_no = p.priv_no AND ug.grp_no = gp.grp_no AND ug.user_no = 54 
AND gp.priv_no NOT IN 
    (SELECT priv_no FROM osqs_users_privileges WHERE user_no = 54 AND "GRANT" = 'N');

在osqs_users_privileges没有行的情况下,此语句(SELECT priv_no FROM osqs_users_privileges WHERE user_no = 54 AND“GRANT”='N')返回0行,即使其他语句返回数据,所有脚本也返回0行。为什么呢?

3 个答案:

答案 0 :(得分:5)

这是由于NOT IN子句中NULL的行为造成的。

例如,

select 'yes' where 3 in (1, 2, 3, null)  -- Return result
select 'yes' where 3 not in (1, 2, null) -- Returns an empty set

为什么呢?因为3 <> null会产生UNKNOWN

  

条件为空

     

评估为UNKNOWN的条件几乎就像FALSE。对于   例如,一个带有WHERE子句中的条件的SELECT语句   计算到UNKNOWN不返回任何行。但是,一个条件评估   UNKNOWN与UNKNOWN的进一步操作不同于FALSE   条件评估将评估为UNKNOWN。因此,不要错   计算结果为TRUE,但NOT UNKNOWN计算结果为UNKNOWN。

Ref

答案 1 :(得分:1)

您需要使用OUTER JOIN:

SELECT p.priv_no FROM osqs_privileges p,osqs_users_privileges up 
WHERE up.priv_no = p.priv_no AND up.user_no = 54 AND up."GRANT" = 'Y' 
    UNION 
SELECT p.priv_no 
FROM osqs_privileges p
LEFT JOIN osqs_groups_privileges gp on osqs_users_groups ug on gp.priv_no = p.priv_no
LEFT JOIN osqs_users_privileges up on ug.grp_no = gp.grp_no
WHERE ug.user_no = 54 
AND gp.priv_no NOT IN 
    (SELECT priv_no FROM osqs_users_privileges WHERE user_no = 54 AND "GRANT" = 'N');

答案 2 :(得分:0)

这是正确的命令:

    SELECT p.priv_no FROM osqs_privileges p,osqs_users_privileges up 
WHERE up.priv_no = p.priv_no AND up.user_no = 55 AND up."GRANT" = 'Y' 
    UNION 
SELECT p.priv_no 
FROM osqs_privileges p 
LEFT JOIN osqs_groups_privileges gp on gp.priv_no = p.priv_no 
LEFT JOIN osqs_users_groups ug on ug.grp_no = gp.grp_no 
LEFT JOIN osqs_users_privileges up on up.priv_no = p.priv_no 
WHERE ug.user_no = 55 
AND gp.priv_no NOT IN 
    (SELECT priv_no FROM osqs_users_privileges WHERE user_no = 55 AND "GRANT" = 'N') ;