Oracle PL/SQL如果找到行,则执行此操作;否则就做点别的

Oracle PL/SQL如果找到行,则执行此操作;否则就做点别的,oracle,plsql,Oracle,Plsql,我正在尝试用pl/sql编写一个过程,它将告诉我谁对Oracle数据库中的所有应用程序表具有SELECT、INSERT、UPDATE和DELETE权限 要么: 用户对该表没有权限 用户基于直接授予(如“将表\u ABC上的选择授予用户\u 123”)对该表拥有权限 用户基于授予的角色对表具有权限,如“将只读角色授予用户”123,其中只读角色包含“将表上的选择授予只读角色” 用户基于系统权限(如选择任何表)对表拥有权限 用户基于DBA这样的角色对表拥有特权,DBA包含SELECT ANY表 现在,

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

要么:

  • 用户对该表没有权限
  • 用户基于直接授予(如“将表\u ABC上的选择授予用户\u 123”)对该表拥有权限
  • 用户基于授予的角色对表具有权限,如“将只读角色授予用户”123,其中只读角色包含“将表上的选择授予只读角色”
  • 用户基于系统权限(如选择任何表)对表拥有权限
  • 用户基于DBA这样的角色对表拥有特权,DBA包含SELECT ANY表
  • 现在,当我硬编码用户或表名时,使用#2(例如)创建过程不会遇到任何错误。但当我试图创建一个包含所有这些场景的过程时,当找不到数据时,我遇到了一个问题

    我可以处理异常,但该过程随后退出。无论是否找到数据,我都无法使代码运行。SQL%NOTFOUND对我不起作用,因为在执行SQL%NOTFOUND的代码之前引发了DATA\u not\u FOUND异常

    我希望发生的是:

  • 该过程循环遍历所有应用程序表
  • 该过程循环遍历所有用户

  • 如果存在直接授权,则variable1='TRUE'或使用SELECT INTO完成相同的操作

  • 如果有角色授予,variable2='TRUE'或使用SELECT INTO完成相同的操作

  • 如果有系统特权授予,variable3='TRUE'或使用SELECT INTO完成相同的操作

  • 如果有DBA角色授予,variable4='TRUE'或使用SELECTINTO完成相同的操作

  • 该过程为上述每个项目打印表名、用户名、是/否

  • 我如何修改代码,以便如果用户_123对表_ABC具有SELECT权限,那么variable1='TRUE',否则variable1='FALSE'?如果dba_选项卡_privs中没有用户_123的记录,则不应引发DATA_NOT_FOUND异常

    事先非常感谢


    大概是这样的:

    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;
    
    异常仅链接到循环内的块,而不是全局异常

    SELECT NVL(MAX(grantee), 'FALSE')
    INTO by_tab_priv
    FROM (
      SELECT
      ...
      MINUS
      SELECT
      ...
    )
    
    块具有如下结构:

    BEGIN
    EXCEPTION 
    END
    

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

    使用以下技巧避免异常

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

    或者,您可以使用
    符号(COUNT(grantee))
    ,它返回
    1
    0

    我试图使用上述代码实现此解决方案。这只是我以后会完善的第一次尝试,但同样的事情正在发生。该过程成功执行,但这只是因为当未找到数据时,它会退出。否,异常被用作流控制,如果找到数据(选择…进入),则执行其他操作。如果未找到数据,则执行其他操作。对于某些用户名,dba\u选项卡中有数据。对其他人来说,没有。如何使其返回到循环并在进入异常块后继续处理记录?我可以在异常块中放一个GOTO语句吗?非常感谢你,瓦伦丁。我也在重写我的查询。我很快就会发出去的。非常感谢你,帕维尔。两种解决方案都有效。如果我想保留计数记录,也可以在var1中选择count(*),然后使用if/else逻辑工作,以防用户被授予2个以上具有重叠权限的角色。如果select into语句无法返回行,则PL/SQL将引发预定义的异常NO_DATA_FOUND,无论是否在下一行选中SQL%NOTFOUND。但是,调用SQL聚合函数的SELECT INTO语句永远不会引发找不到的数据,因为这些函数总是返回值或null。在这种情况下,SQL%NOTFOUND生成FALSE。