2012-11-28 142 views

回答

4

既然你可以GRANT/REVOKE一次身兼數職,一個DO命令與動態SQL會更簡單/快(基於集合的操作經常要更快一些在RDBMS比循環):

DO 
$$ 
BEGIN 
EXECUTE (
    SELECT 'REVOKE ' || string_agg(quote_ident(rolname), ', ') 
      || ' FROM ' || u.usename 
    FROM pg_user   u 
    JOIN pg_auth_members m ON (m.member = u.usesysid) 
    JOIN pg_roles  r ON (r.oid = m.roleid) 
    WHERE u.usename = 'my_user' 
    GROUP BY u.usename 
    ); 
END 
$$ 

DO命令以及string_agg() aggregate function需要PostgreSQL 9.0或更高版本。

quote_ident()確保非標準標識符不會造成麻煩(包括SQL注入)。

有效執行如下命令:

REVOKE role_a, role_b, "FROM postgres; DELETE * FROM usr; --" FROM my_user; 

,如果沒有格蘭特的發現不會做任何事情。
Note the tricky name in double quotes, but properly quoted by quote_ident().

BTW:這個撤銷所有格蘭特的 「組角色」 與否。這些都只是PostgreSQL的角色,有些具有LOGIN權限,有些則不具備(「組角色」)。 usergroup之間的區別是歷史。

+0

謝謝Erwin的回答。 –

0

認爲需要通過結果撤銷rolname FROM USENAME查詢所有角色

select usename, rolname 
from pg_user 
join pg_auth_members on (pg_user.usesysid=pg_auth_members.member) 
join pg_roles on (pg_roles.oid=pg_auth_members.roleid) 

和LOOP;