2011-07-24 126 views
0

我寫這篇聲明,在osqs_users_privileges沒有行及本聲明的情況下正常工作在所有情況下,除了一種情況這個sql語句有什麼問題?

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'); 

(priv_no SELECT FROM osqs_users_privileges WHERE user_no = 54和「GRANT」 =「N」 )返回0行,即使其他選擇語句返回數據,所有腳本都會返回0行。爲什麼?

回答

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'); 
+0

,, 它給出了一個錯誤:無效的關係運算符在這一行 LEFT JOIN osqs_groups_privileges GP在osqs_users_groups ug上gp.priv_no = p.priv_no – sahar

+0

非常感謝你,你給我的方式。 但我改變了你的答案 – sahar

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

Nulls in Conditions

A condition that evaluates to UNKNOWN acts almost like FALSE. For example, a SELECT statement with a condition in the WHERE clause that evaluates to UNKNOWN returns no rows. However, a condition evaluating to UNKNOWN differs from FALSE in that further operations on an UNKNOWN condition evaluation will evaluate to UNKNOWN. Thus, NOT FALSE evaluates to TRUE, but NOT UNKNOWN evaluates to UNKNOWN.

Ref

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') ;