Oracle SQL-“表不存在”时UNION中断

时间:2018-08-19 18:21:27

标签: sql oracle

我是Oracle SQL的新手(无论如何,通常对SQL都没有经验)。如果能解决我的问题,我将不胜感激。

我需要查询几个表和视图(大约30个),并作为所有对象的UNION并返回一个结果集。但是,某些表可能存在也可能不存在。我知道要查询的所有30个表/视图的确切名称。在执行大型UNION之前,我可能会执行其他查询,但是最终,我必须返回所有行的单个结果。我无法在SQL脚本中“定义”变量。

这些是我所无法控制的约束。为了使用现有的工作流程,我必须在这些限制内进行操作。

问题在于,如果任何表/视图都不存在,则整个UNION都会失败,并且我将不会获得任何结果。我是在第一次出现丢失的视图/表时得到的:

SQL Error: ORA-00942: table or view does not exist
00942. 00000 -  "table or view does not exist"
*Cause:    
*Action:

我希望能够不中断地进行处理。我想简单地跳过丢失的表并返回剩余的行(尽管我知道这是不好的设计,试图在不知道表是否存在的情况下进行查询)。如果我最终包含错误消息是可以的,因为这些错误消息最终将被解析器跳过。

我有这样的东西。如果不存在任何视图,那么一切都会失败,并且我不会获得任何结果:

select col1 || col2 || ... from view1
union
select col1|| col2 || ... from view2
union
select name from view3
.  
.
select ... from view30;

如果有帮助,我可以切换到PL / SQL。我没有使用PL / SQL的丰富经验,但是如果它可以解决问题,我可以使用它。我对PL / SQL进行了一些阅读,但无法找出一些简单的方法。

我们非常感谢您的帮助。让我知道是否可以提供其他详细信息。

谢谢。

1 个答案:

答案 0 :(得分:1)

同事不是说您不能那样做-他们是说您不应该这样做,这是根本问题的原因。但是这个世界并不完美-它常常会给您锯,并告诉您锤钉子。您的问题有一个解决方案-它涉及动态SQL和一些自定义PL / SQL代码。简化的解决方案:

创建一个包和一个函数:

function does_tbl_exists(p_tbl_name in varchar2) return number is

  l_stmt varchar2(60);

begin

  l_stmt := 'select count(*) from ' ||p_tbl_name;
  execute immediate l_stmt;
return 1;
exception
  when others then
    return 0 ;
end;

使用一些数据创建了一个测试表TEST_TBL。然后,我们在pl / sql块中构建SQL语句:

declare

  l_count number;
  l_stmt varchar2(400);
  l_tab_name_1 varchar2(30) := 'TEST_TBL';
  l_tab_name_2 varchar2(30) := 'TEST_TBL2';

begin

  if test_pck.does_tbl_exists(p_tbl_name => l_tab_name_1) = 1 then
    l_stmt := 'select count(*) count_number from ' || l_tab_name_1;
  end if;

  if test_pck.does_tbl_exists(p_tbl_name => l_tab_name_2) = 1 then

    if l_stmt is not null then
      l_stmt := l_stmt || ' union all' || chr(10);
    end if;

    l_stmt := l_stmt || 'select count(*) count_number from ' || l_tab_name_2;

  end if;

  if l_stmt is not null then

    l_stmt := 'select sum(tmp.count_number) from (' || l_stmt || ') tmp';

    dbms_output.put_line(l_stmt);
    execute immediate l_stmt into l_count;
    dbms_output.put_line('count: '||l_count);


  else

    dbms_output.put_line('Nothing todo.');

  end if;

end;

通过此模板,您可以构建最终的SQL语句。 但是,将其作为最后的手段-我认为您仍然应该去找高层人士,并与他们交谈,他们目前的“要求”是“不好的”,他们应该感到“不好”(在此处插入模因)。