简体   繁体   English

oracle调用存储过程里面选择

[英]oracle call stored procedure inside select

I'm working on a query (a SELECT) and I need to insert the result of this one in a table. 我正在处理一个查询(一个SELECT),我需要在表中插入这个结果。 Before doing the insert I have some checking to do, and if all columns are valid, I will do the insert. 在进行插入之前,我有一些检查要做,如果所有列都有效,我将进行插入。

The checking is done in a stored procedure. 检查在存储过程中完成。 The same procedure is used somewhere else too. 在其他地方也使用相同的程序。 So I'm thinking using the same procedure to do my checks. 所以我在考虑使用相同的程序进行检查。

The procedure does the checkings and insert the values is all OK. 该程序执行检查并插入值即可。

I tryied to call the procedure inside my SELECT but it does not works. 我试图在我的SELECT中调用该过程,但它不起作用。

SELECT field1, field2, myproc(field1, field2)

from MYTABLE.

This kind of code does not works. 这种代码不起作用。

I think it can be done using a cursor, but I would like to avoid the cursors. 我认为可以使用游标完成,但我想避免使用游标。 I'm looking for the easiest solution. 我正在寻找最简单的解决方案。

Anybody, any idea ? 任何人,任何想法?

use a PL/SQL loop: 使用PL / SQL循环:

BEGIN
   FOR c IN (SELECT field1, field2 FROM mytable) LOOP
       my_proc(c.field1, c.field2);
   END LOOP;
END;

SQL can only use functions in the projection: it needs something which returns a value. SQL只能使用投影中的函数:它需要返回值的东西。 So you are going to have to write some functions. 所以你将不得不写一些函数。 That's the bad news. 这是坏消息。 The good news is, you can re-use all the investement in your stored procedures. 好消息是,您可以在存储过程中重复使用所有投资。

Here is a procedure which enforces a completely just business rule: only managers can have a high salary. 这是一个强制执行完全公正的业务规则的程序:只有经理才能获得高薪。

SQL> create or replace procedure salary_rule
  2      ( p_sal in emp.sal%type
  3        , p_job in emp.job%type)
  4  is
  5      x_sal exception;
  6  begin
  7      if p_sal > 4999 and p_job != 'MANAGER' then
  8          raise x_sal;
  9      end if;
 10  exception
 11      when x_sal then
 12          raise_application_error(-20000, 'Only managers can earn that much!');
 13  end salary_rule;
 14  /

Procedure created.

SQL>

Because it is a procedure we cannot use it in a SELECT statement; 因为它是一个过程,我们不能在SELECT语句中使用它; we need to wrap it in a function. 我们需要将它包装在一个函数中。 This function just calls the stored procedure. 此函数只调用存储过程。 It returns the input parameter P_SAL. 它返回输入参数P_SAL。 In other words, if the salary is valid (according to the rules) it will be returned. 换句话说,如果工资有效(根据规则),它将被退回。 Otherwise the function will re-hurl the stored procedure's exception. 否则,该函数将重新抛出存储过程的异常。

SQL> create or replace function validate_salary
  2      ( p_sal in emp.sal%type
  3        , p_job in emp.job%type)
  4      return emp.sal%type
  5  is
  6  begin
  7      salary_rule(p_sal, p_job);
  8      return p_sal;
  9  end validate_salary;
 10  /

Function created.

SQL>

The function has to return a value which we want to insert into our table. 该函数必须返回一个我们想要插入表中的值。 It cannot return some meaningless phrase like "salary okay". 它不能返回一些毫无意义的短语,如“薪水好”。 Also, if we want to validate two columns we need a separate function for each, even if there is a relationship between them and we use the same stored procedure to validate them both. 此外,如果我们想要验证两个列,我们需要为每个列分别使用一个函数,即使它们之间存在关系,我们也使用相同的存储过程来验证它们。 Good use for the DETERMINISTIC keyword. 适用于DETERMINISTIC关键字。

Here's the test: plumbers cannot earn 5000 spondulicks .... 这是测试:管道工无法获得5000个spondulicks ....

SQL> insert into emp
  2      (empno
  3      , ename
  4      , job
  5      , deptno
  6      , sal )
  7  select
  8      emp_seq.nextval
  9      , 'HALL'
 10      , 'PLUMBER'
 11      , 60
 12      , validate_salary(5000, 'PLUMBER')
 13  from dual
 14  /
    , validate_salary(5000, 'PLUMBER')
      *
ERROR at line 12:
ORA-20000: Only managers can earn that much!
ORA-06512: at "APC.SALARY_RULE", line 12
ORA-06512: at "APC.VALIDATE_SALARY", line 7


SQL>

... but managers can (because they deserve it): ......但管理者可以(因为他们应得):

SQL> insert into emp
  2      (empno
  3      , ename
  4      , job
  5      , deptno
  6      , sal )
  7  select
  8      emp_seq.nextval
  9      , 'HALL'
 10      , 'MANAGER'
 11      , 60
 12      , validate_salary(5000, 'MANAGER')
 13  from dual
 14  /

1 row created.

SQL>

Note that the hurled exception is crucial to this working. 请注意,抛出的异常对于此工作至关重要。 We cannot write some bizarre IF SALARY IS VALID THEN INSERT logic in our SQL statement. 我们不能在SQL语句中写一些奇怪的IF SALARY IS VALID THEN INSERT逻辑。 So, if the stored procedure doesn't raise an exception but instead returns some wimpy error status the wrapping function will have to interpret the output and hurl its own exception. 因此,如果存储过程没有引发异常但是返回一些wimpy错误状态,则包装函数将必须解释输出并抛出其自己的异常。

You can't use stored procedures in SELECT statement. 您不能在SELECT语句中使用存储过程。 You can use functions for that. 你可以使用它的功能。

As I understand you are calling insert in your SP, so take into consideration that you can's use INSERT/UPDATE in function body. 据我所知,你在SP中调用insert,所以考虑到你可以在函数体中使用INSERT / UPDATE。 But if you need to do some checks you can use function which will do that checks and use that function in your select statement. 但是如果你需要做一些检查,你可以使用将执行该检查的函数并在select语句中使用该函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM