在过程中构造和调试PL / SQL简单或复杂的选择视图语句

时间:2015-02-24 02:31:39

标签: oracle plsql oracle11g oracle10g toad

如何使用存储过程在oracle pl / sql中对相当简单的视图执行选择。

让我们说这个观点看起来像这样:

FirstName   LastName
--------    -------
Bob         Jones
James       Kay
etc...

对我而言应该这么简单:

Procedure SuperSimple()
begin
  select FirstName, LastName from SuperSimple
end

但是我被告知这不起作用。

所以我尝试使用PL / SQL游标。仍在试图找出我使用游标的原因。但它似乎在11g中是必要的。

Procedure AlphaPrime(Results OUT Ref CURSOR) IS
begin
OPEN Results for 
  select FirstName, LastName from SuperSimple;
end;

现在我希望这会有效但我用select语句做这样的事情似乎没有用。

我还需要添加一个fetch和另一个open和close命令来使这个东西工作吗?这一切背后的想法是什么?我注意到,在我阅读的大多数文档中,试图找到有关如何向程序添加非常简单的选择状态的信息似乎都缺失了。是否有一个原因就像将一个select语句添加到过程一样简单,因为将它添加到视图会更好。这些方面的东西。

我遇到的问题是,我想要开始时非常简单,并且随着时间的推移,对于sproc的复杂程度会更加复杂......时间大约为1到2小时。有人能指出我在Oracle PL / SQL中的一些文档,它们展示了如何添加一个简单的表或视图。此外,如果不允许特定视图或表的权限,则该用户只会失败,或者是否为空结果集。

2 个答案:

答案 0 :(得分:2)

从您的问题中不清楚您打算如何处理程序中的查询结果。所以在这里我用dbms_output做一些例子,它打印出来以查询查询中的一些消息和数据。可能你会用你的逻辑代替它。

让我们有一些观点(实际上,无论你是查询视图还是表格都没关系,但我会坚持你的问题)

 create table some_simple_table(firstname varchar2(30), lastname   varchar2(30));
 / 
   create or replace view supersimple_view as select firstname, lastname,    'whatever1' whatever from some_simple_table;
 /

以下代码确实选择变量,这仅在查询返回恰好一行时才有效。

 create or replace procedure supersimple1 is
    vfirstname supersimple_view.firstname%type;
    vwhatever supersimple_view.whatever%type;
    vsupersimple supersimple_view%rowtype;
 begin
    select firstname, whatever into vfirstname, vwhatever from    supersimple_view;  
    dbms_output.put_line('I''m doing some logic with this'|| vwhatever );
    select * into vsupersimple from supersimple_view;
    dbms_output.put_line('I''m doing some logic with this'||   vsupersimple.firstname);
end;
    /

也许你可以通过结果实现隐式游标循环并做一些逻辑。

create or replace procedure supersimple2 is
 begin
  for rec in (select * from supersimple_view)
  loop
      dbms_output.put_line('I''m doing some logic with this record '||   rec.firstname);
  end loop;
  end;
 /

另一个选项是游标(特别是当你将重用相同的选择时)循环结果并做一些逻辑。

 create or replace procedure supersimple3 is
  cursor cur is (select * from supersimple_view);
    vsupersimple cur%rowtype;
 begin
 open cur ;
  loop
    FETCH cur INTO vsupersimple;
    EXIT WHEN cur%NOTFOUND; 
    dbms_output.put_line('I''m doing some logic with this record '|| vsupersimple.firstname);
  end loop;
 close cur;
end;

/

您可以将查询结果提取到集合

create or replace procedure supersimple4 is
type supersimple_colt is table of supersimple_view%rowtype index by    pls_integer;
vsupersimple_col supersimple_colt; 
begin
  select * bulk collect into vsupersimple_col from supersimple_view ;
  for i in 1 .. vsupersimple_col.count
  loop
           dbms_output.put_line('I''m doing some logic with this record '||  vsupersimple_col(i).firstname);
  end loop;
 end;
/

您可以创建独立的数据库SQL类型并使用它们来获取结果,而不是在supersimple4中声明的PL / SQL类型。这个方法为您提供了各种功能:在表格中的select语句中查询集合的可能性,通过xmltype将其转换为xml等。

答案 1 :(得分:0)

我想我找到了答案。对于选中的每个列,它需要视图或表列类型,这类似于用于最终输出的参数列表。这样,当你宣布它时,你可以更好地知道你得到了什么,哪种有意义。

因此,如果您有两个用于生成输出列的表或视图,则需要在描述性OUT变量中使用这些表或视图来更好地描述在最终输出结果中输出的内容。

请参阅此link

我正在接受这个下一部分的有根据的猜测,因为我刚刚开始理解它:

此查询应该有效。但如果不是它可能是由于不充分的特权。尝试一个您知道可以访问的表,并在调试模式下的过程中选择它。然后尝试一个视图。

Procedure AlphaPrime(Results OUT Ref CURSOR) IS
begin
OPEN Results for 
  select FirstName, LastName from SuperSimple;
end;

此外,调试模式和您指定的用户角色可能没有足够的权限来调试视图中的所有对象,并且可能无法访问它们。有时你可以点击"忽略" Toad中的按钮跳过存储过程内的调试。此外,您可能有兴趣查看结果,对象只是不查看其结构,这也可能会给您不足的特权错误。再次忽略它们以跳过这些类型的问题并在调试模式下查看结果。如果你没有调试这个,那么你不应该看到任何错误,只是得到结果。