绕过没有数据执行的Oracle PL / SQL

时间:2017-08-23 16:29:33

标签: oracle plsql

我正在尝试根据给每个用户的不同级别检查菜单中条目的两种授权级别。

但是oracle sql中没有数据异常阻止我检查第二个表是否有授权。

这是我的代码:

declare 
  v_count number;
  v_name varchar2(255);
begin
  select DASHBOARD into v_count from RCM_ADMINISTRATOR where USER_NAME = :APP_USER;
  select MANAGER into v_name from RCM_ADMINISTRATION_TEAMS where MANAGER = :APP_USER;

  if v_count >= 1 then
    return true;
  end if;
  if v_name is not null then
      return true;
  end if;
  if v_count = 0 then
   return false;
  end if;
EXCEPTION WHEN NO_DATA_FOUND THEN
 return false;

end; 

有没有办法让它如果我从第一个查询中得不到数据,我仍然可以运行第二个查询?

2 个答案:

答案 0 :(得分:3)

这是一个非常常见的问题,有许多解决方案。

一个选项是在您尝试执行的每个SELECT INTO周围放置一个BEGIN / EXCEPTION / END块。

declare 
  v_count number;
  v_name varchar2(255);
begin
  BEGIN
    select DASHBOARD into v_count from RCM_ADMINISTRATOR where USER_NAME = :APP_USER;
  EXCEPTION when no_data_found THEN v_count := null;
  END;
  BEGIN
    select MANAGER into v_name from RCM_ADMINISTRATION_TEAMS where MANAGER = :APP_USER;
  EXCEPTION when no_data_found THEN v_name := null;
  END;

  if v_count >= 1 then
  ...etc...

我经常发现使用MAX更容易:

declare 
  v_count number;
  v_name varchar2(255);
begin
  select max(DASHBOARD) into v_count from RCM_ADMINISTRATOR where USER_NAME = :APP_USER;
  select max(MANAGER) into v_name from RCM_ADMINISTRATION_TEAMS where MANAGER = :APP_USER;

  if v_count >= 1 then
  ...etc...

这是一种懒惰的技术,如果你不小心,它可以掩盖ORA-01422错误(确切的提取返回超过请求的行数)。但是如果你知道你的查询只返回0或1行,那么它将正常工作。

答案 1 :(得分:1)

您的代码存在一些问题。您正在使用匿名块并返回值,这是不可能的。您可以编写一个返回BOOLEAN值(TrueFalse)的函数。但是,根据Oracle文档,它没有用处 http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/datatypes.htm#CJACJGBG

  

您无法将值TRUEFALSE插入数据库列。   您无法在BOOLEAN变量中选择或获取列值。   从SQL查询调用的函数不能使用任何BOOLEAN参数。   内置SQL函数(例如TO_CHAR)也不能;代表   输出中的BOOLEAN值,必须使用IF-THEN or CASE构造   将BOOLEAN值转换为其他类型,例如0或1,'Y'或   'N','true'或'false'等等。

因此,在代码中,VARCHAR2用作RETURN参数。

APP_USER作为函数参数传递,而不是使用绑定变量。

对于您的条件,每个查询必须执行而不管异常,您可以将它放在单独的BEGIN..END块中。

从存储过程中使用RETURN后,在尝试实现异常后,无法跳回到代码的其余部分。相反,如果不满足其他条件,请使用前一个exit_code之前的代码将值存储在变量RETURNEND中以最终返回退出代码。

CREATE OR REPLACE FUNCTION f_test_ret(p_app_user IN VARCHAR2)  
  RETURN VARCHAR2
AS
  v_count   NUMBER;
  v_name    VARCHAR2(255);
  exit_code VARCHAR2(6);
BEGIN
  BEGIN
    SELECT DASHBOARD
    INTO v_count
    FROM RCM_ADMINISTRATOR
    WHERE USER_NAME = p_app_user;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    exit_code := 'FALSE';
  END;
  BEGIN
    SELECT MANAGER
    INTO v_name
    FROM RCM_ADMINISTRATION_TEAMS
    WHERE MANAGER = p_app_user;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    exit_code := 'FALSE';
  END;
  IF v_count >= 1 THEN
    RETURN 'TRUE';
  END IF;
  IF v_name IS NOT NULL THEN
    RETURN 'TRUE';
  END IF;
  IF v_count = 0 THEN
    RETURN 'TRUE';
  END IF;
  RETURN exit_code;
END;
/