【问题标题】:The same PL/SQL function returns two different values同一个 PL/SQL 函数返回两个不同的值
【发布时间】:2016-01-25 13:54:58
【问题描述】:

我有一个 PL/SQL 函数来检查角色是否对某个对象具有特权

CREATE OR REPLACE FUNCTION HasPrivilegeOnObject(rolename      IN VARCHAR2,
                                                objectname    IN VARCHAR2,
                                                objectowner   IN VARCHAR2,
                                                privilegename IN VARCHAR2)
  RETURN NUMBER
AS
  output NUMBER;
  BEGIN
    SELECT count(*) INTO output
    FROM dba_tab_privs
    WHERE
      grantee = rolename AND
      owner = objectowner AND
      table_name = objectname AND
      privilege = privilegename;

    IF output > 0 THEN
      output := 1;
    END IF;

    RETURN output;
  END hasprivilegeonobject;

我会检查它:

call dbms_output.put_line(HasPrivilegeOnObject('Role1','Table1','TableOwner','UPDATE'));

结果是:1;

但是当我运行与函数内部相同的查询时:

    select count(*) from DBA_TAB_PRIVS where 
        GRANTEE = 'Role1' and
        OWNER = 'TableOwner' and
        TABLE_NAME = 'Table1' and
        Privilege = 'UPDATE';  

结果为 0。

有人知道这是怎么回事吗?

【问题讨论】:

  • 在你的函数 ObjectName "Table1" 被用于 TABLE_NAME 过滤器,但是在实际查询中它使用 RoleName "Role1",因此我相信结果不同。
  • 两种情况下参数不同可能导致o/p不同。
  • 将查询复制到 Stackoverflow 时实际上是一个错误 :) !我编辑了线程。
  • 这就是更改发布内容的问题;有可能(甚至在这种情况下可能)您在两个示例中使用的值有所不同,但是因为您已经更改了它们,所以我们无法发现它。我猜你有错字或交换了两个字段,但这只能是一个猜测,唉。
  • 在查询中添加“where rownum 0 ...”代码了。

标签: oracle


【解决方案1】:

确保对象名称使用大写字母,即使在将对象名称作为参数传递时也是如此,除非您专门使用双引号创建了对象。如果在创建对象名称时不使用双引号,则对象名称在内部存储为大写。

您没有初始化输出 - 函数的返回值。如果查询不匹配任何行会发生什么?这意味着返回值可能是不确定的。

除非您专门使用双引号将 Table1 命名为 Table1(在创建 Table1 时),否则 Table1 将被存储在内部,在数据字典中作为 TABLE1。这意味着如果函数中的查询使用 'Table1' 的 ObjectName(表名)参数调用,它可能不一定匹配任何行。

这也不是必需的,但最好在函数中添加异常处理程序以确保异常不会阻止返回值完全按预期设置..

【讨论】:

  • 虽然我同意大写的问题,但在发布的版本中这些值已被替换,所以不清楚这是否真的是一个原因,尽管它很可能是(见我之前的评论 *8- )。不初始化output 不是问题; count(*) 必须向该变量返回一个值。如果查询以某种方式失败,则该函数将抛出异常 - 添加处理程序('when others`!?)更有可能掩盖问题而不是帮助识别问题,不是吗?
  • 嗨..我重新检查了帖子,我仍然看到帖子有 Table1 不是大写的;自从我现在检查以来,它可能已经更新;我注意到如果 PLSQL 查询返回零行,ORACLE 不会抛出异常;如果查询在语法上有效并且引用了有效对象,但不匹配任何行,则不抛出异常;我试图找出在没有匹配行的情况下这段代码将如何初始化。
  • 是的,但是对于函数调用和简单查询,示例都显示为'Table1'(等);如果它(只是)一个案例问题,那么两者都不会找到任何赠款。因此,要么真正的查询使用大写名称,要么一个使用大写,一个不使用 - 但这是由 OP 隐藏的,没有显示正在使用的实际、真实的值。总的来说,您是对的,但我认为我们没有足够的信息来说明这就是问题所在 - 尽管如果使用了不一致的值很可能会出现问题。如果没有匹配的行,count(*) 仍将output 设置为0 - 它不能 设置output
  • 好的;但为什么他的帖子说 SQL SELECT(非 PLSQL 查询)返回计数为零?零不意味着数据字典中不匹配吗?这似乎与内部命名为 TABLE1 而不是 Table1 的表一致。有谁知道他的哪个查询返回 Table1(而不是 TABLE1)的非零计数?也许我还没有看到他的最新动态。
  • 因为Table1 不是真正的表名;这些值已针对该问题进行了更改。查询应该返回相同的计数,if 值相同。因此它们不是 - 但是因为它们已经针对问题进行了更改(我猜是为了隐藏真实的模式),所以在真实的、未更改的查询中 OP 有什么问题并不明显。错字、大小写错误、值未与右列对齐 - 我们只能猜测。
猜你喜欢
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
相关资源
最近更新 更多