PL / SQL如果找到行,则执行此操作;否则做其他事

时间:2015-05-19 20:13:40

标签: oracle plsql

我正在尝试在pl / sql中编写一个过程,它将告诉我谁对Oracle数据库中的所有应用程序表都有SELECT,INSERT,UPDATE,DELETE权限。

或者:

  1. 用户对表格没有任何权限
  2. 用户具有基于直接授权的表格权限,例如“在table_ABC上授予select to user_123”
  3. 用户具有基于授权角色的权限,例如“将read_only_role授予user_123”,其中read_only_role包含“table_ABC上的grant select to read_only_role”
  4. 用户根据SELECT ANY TABLE
  5. 等系统权限对表具有权限
  6. 用户具有基于DBA等角色的权限,该角色包含SELECT ANY TABLE。
  7. 现在,当我对用户或表名进行硬编码时,我没有遇到使用#2(例如)创建过程的错误。但是当我尝试创建包含所有这些场景的1个过程时,我在DATA_NOT_FOUND时遇到了问题。

    我可以处理异常,但程序会在之后退出。无论是否找到数据,我都无法运行代码。 SQL%NOTFOUND对我不起作用,因为在执行SQL%NOTFOUND的代码之前引发了DATA_NOT_FOUND异常。

    我想要发生的是:

    1. 该过程循环遍历所有应用程序表
    2. 该程序循环遍历所有用户

    3. 如果有直接授权,变量1 ='TRUE'或使用SELECT INTO完成同样的事情

    4. 如果有角色授予,变量2 ='TRUE'或使用SELECT INTO完成同样的事情

    5. 如果有系统权限授予,变量3 ='TRUE'或使用SELECT INTO完成相同的事情

    6. 如果有DBA角色授权,变量4 ='TRUE'或使用SELECT INTO完成同样的事情

    7. 该程序为上述每个项目打印表名,用户名,是/否。

    8. 如何修改代码,以便如果User_123对Table_ABC具有SELECT权限,则variable1 ='TRUE',否则variable1 ='FALSE'?如果dba_tab_privs中没有User_123的记录,则不应引发DATA_NOT_FOUND异常。

      非常感谢你。

      DECLARE
        by_tab_priv varchar(20);
      
      BEGIN
      
        dbms_output.enable(1000000);
      
        FOR x IN ( SELECT table_name
                 FROM dba_tables
                 WHERE owner IN ('NIKUP')
                 ORDER BY table_name )
        LOOP
      
          BEGIN
      
            FOR y IN ( SELECT username from dba_users
                 ORDER BY username)
            LOOP
      
      
              SELECT grantee 
              INTO by_tab_priv 
              FROM dba_tab_privs 
              WHERE    grantee=y.username 
                   and table_name=x.table_name 
                   and privilege in ('SELECT')
              MINUS
              SELECT granted_role 
              FROM dba_role_privs 
              WHERE granted_role in (
                      SELECT grantee 
                      FROM dba_tab_privs 
                      WHERE     grantee=y.username 
                            and table_name=x.table_name 
                            and privilege in ('SELECT'));
      
              BEGIN
                dbms_output.put_line(y.username || ' ' || by_tab_priv);
              END;
      
             END LOOP;
           END;
         END LOOP;
         EXCEPTION
          WHEN NO_DATA_FOUND THEN
            by_tab_priv:='FALSE';
       END;
      

2 个答案:

答案 0 :(得分:0)

这样的事情:

begin
  select ... into ;
  var1 :=TRUE;
exception
  when NO_DATA_FOUND then  -- controlling the case with no_data_found
    var1 := FAlSE;

结束;

<强>更新

  LOOP
   BEGIN
    SELECT grantee 
    INTO by_tab_priv 
    FROM dba_tab_privs 
    WHERE    grantee=y.username 
         and table_name=x.table_name 
         and privilege in ('SELECT')
    MINUS
    SELECT granted_role 
    FROM dba_role_privs 
    WHERE granted_role in (
            SELECT grantee 
            FROM dba_tab_privs 
            WHERE     grantee=y.username 
                  and table_name=x.table_name 
                  and privilege in ('SELECT'));


    dbms_output.put_line(y.username || ' ' || by_tab_priv);

   EXCEPTION
    WHEN NO_DATA_FOUND THEN
     by_tab_priv:='FALSE';
   END;

 END LOOP;

异常仅链接到循环内的块,它不是全局异常

块具有如下结构:

BEGIN
EXCEPTION 
END

你可以在一个函数中有多个块,每个块都可以自己处理异常。

答案 1 :(得分:0)

使用以下技巧来避免异常

SELECT NVL(MAX(grantee), 'FALSE')
INTO by_tab_priv
FROM (
  SELECT
  ...
  MINUS
  SELECT
  ...
)

或者您可以使用SIGN(COUNT(grantee)),它会返回10