1
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;
4

3 回答 3

4

SQL 语句中不允许使用过程,因为混合使用声明式和命令式编程风格会造成混淆。

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

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

select *
from table1
where id = 1
    and pr;

即使在select列表中使用了一个过程,它也可能没有意义。例如,总是忽略selectan 中的列表。exists

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

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

于 2013-07-10T06:08:12.317 回答
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
于 2013-07-10T05:15:12.070 回答
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;
于 2017-06-20T09:28:57.273 回答