为什么我们不能在oracle中的select语句中执行存储过程?有什么有力的理由吗?

时间:2013-07-10 03:32:00

标签: oracle oracle10g

create or replace procedure pr
is
    v_date date; 
begin
    select sysdate into v_date from dual;
    DBMS_output.put_line(v_date);
end pr;

3 个答案:

答案 0 :(得分:4)

SQL语句中不允许使用过程,因为混合声明性和命令式编程样式会让人感到困惑。

SQL语句是一个条件列表 - 由Oracle决定如何生成与这些条件匹配的结果集。 PL / SQL存储过程是一组以非常可预测的方式改变事物的指令。

在下面的示例中,pr应执行多少次?它是在id = 1之前还是之后执行的?如果SQL语句具有预定义的顺序,那么优化器将无法推送谓词,合并子查询等,并且性能将是不可接受的。

select *
from table1
where id = 1
    and pr;

即使在select列表中使用过程,也可能没有意义。例如,select内的exists列表始终被忽略。

select * from dual where exists (select pr from dual);

但实际上SQL语句有时需要与外界进行交互,并且需要一些程序逻辑。允许使用函数,因为它们通常只是计算某些东西并返回一个值。功能通常不依赖于程序状态,并且有很多副作用。您的函数可以使用会话变量,更新表(如果它设置为PRAGMA AUTONOMOUS TRANSACTION),设置上下文等.Oracle不能阻止您做这些事情,但禁止SQL中的过程声明至少会阻止这样的代码。

答案 1 :(得分:1)

无法使用select语句执行过程,如果要使用select语句执行,可以使用函数。

如果你想使用select语句执行过程,那么一种方法是使用函数包装你的过程并使用select语句调用函数。

CREATE OR REPLACE PROCEDURE pr (o_param OUT DATE)
IS
    v_date  DATE;
BEGIN
    SELECT  SYSDATE
      INTO  v_date
      FROM  DUAL;

    o_param := v_date;
END pr;

现在用函数

包装过程
CREATE OR REPLACE FUNCTION my_funct
    RETURN DATE
AS
    o_param  DATE;
BEGIN
    pr (o_param);

    RETURN o_param;
EXCEPTION
    WHEN NO_DATA_FOUND
    THEN
        DBMS_OUTPUT.put_line (
        DBMS_UTILITY.format_error_backtrace || ' ' || SQLERRM
    );
                -- raise exception 
    WHEN OTHERS
    THEN
        DBMS_OUTPUT.put_line (
        DBMS_UTILITY.format_error_backtrace || ' ' || SQLERRM
    );
                -- raise exception  
END my_funct;
/

使用select语句

调用该函数
SELECT my_funct  FROM DUAL

答案 2 :(得分:0)

CREATE OR REPLACE PROCEDURE count_salas IS   V_count NUMBER(3);    
BEGIN   
SELECT COUNT(SALES.SALEQTY) as sales INTO V_count 
FROM SALES INNER JOIN EMPLOYEE ON EMPLOYEE.EMPID = SALES.EMPID WHERE EMPLOYEE.EMPID = '101';

DBMS_OUTPUT.PUT_LINE(V_count);    END  V_count;