如何创建一个可以全局访问的变量-oracle

时间:2019-01-17 13:17:35

标签: sql oracle plsql

CREATE OR REPLACE PROCEDURE cost_proportion(
    p_assignment_id IN NUMBER,
    p_proportion    IN NUMBER,
    p_old_value     IN NUMBER,
    p_cost_alloc_id IN NUMBER,
    p_cost_code     IN VARCHAR2,
     p_date_from in date,
    p_flag IN VARCHAR2 )
IS
  PRAGMA AUTONOMOUS_TRANSACTION;
  v_flag NUMBER :=0;

BEGIN

  IF p_flag = 'V' 
  THEN
    --            IF p_old_value > 0 THEN

            DELETE
            FROM cost_temp
            WHERE 1=1
               and cost_code = p_cost_code
              --AND
            AND assignment_id = p_assignment_id;



    IF SQL%ROWCOUNT = 0 THEN
          DELETE
          FROM cost_temp
          WHERE cost_allocation_id = p_cost_alloc_id
          AND assignment_id        = p_assignment_id;
    END IF;
    --            END IF;
    INSERT
    INTO cost_temp VALUES
      (
        p_assignment_id,
        p_proportion,
        p_old_value,
        p_cost_alloc_id,
        p_cost_code,
        p_flag
      );
    COMMIT;
  ELSIF p_flag = 'P' THEN
    DELETE FROM ecost_temp WHERE assignment_id = p_assignment_id;
    INSERT INTO cost_temp
          SELECT assignment_id,
            proportion * 100,
            0,
            cost_allocation_id,
            b.segment1
            || '|'
            || b.segment3
            || '|'
            || b.segment2
            || '|'
            || b.segment4
            || '|'
            || b.segment6,
            p_flag
          FROM pay_cost_allocations_f a,
            pay_cost_allocation_keyflex b
          WHERE a.cost_allocation_keyflex_id = b.cost_allocation_keyflex_id
          AND a.assignment_id                = p_assignment_id
          AND sysdate BETWEEN a.effective_start_date AND a.effective_end_date;

    COMMIT;


  ELSIF p_flag = 'D' THEN
        DELETE
        FROM cost_temp
        WHERE cost_code = p_cost_code
        AND proportion  = p_proportion;
    COMMIT;
  END IF;
END;

在上面的查询中,我希望每当执行p_flag ='P'部分时,都将设置一个变量值。此值应为固定值,下次运行此过程时可以访问。这可能吗?

例如:执行p_flag ='P'时,v_flag = 2。

当再次由另一个块调用此过程时,该值仍为v_flag = 2

2 个答案:

答案 0 :(得分:2)

在PL / SQL中,全局变量只能存在于程序包中。这是因为PL / SQL每次调用过程时都会初始化过程级别变量。只有包允许我们在过程范围之外定义变量。

此玩具包将在多次调用n时保持gvar_test.incr()的值。

create or replace package gvar_test as
     procedure incr (p_in in number, p_out out number);
end gvar_test; 
/
create or replace package body gvar_test as
     n pls_integer;

     procedure incr (p_in in number, p_out out number) is
     begin
         n := n + p_in;
         p_out := n;
     end incr;
begin
    -- initialise variable first time package is called 
    n := 0;
end gvar_test; 
/

全局变量是一件棘手的事情。许多人认为使用它们是不好的做法,主要是因为很容易迷失状态。当我们使用通过连接池的Web应用程序时,尤其如此。 PL / SQL变量保存在会话内存中,因此对于在每次调用都可以切换到随机会话的环境中持久保存跨调用状态没有用。在这种情况下,您应该使用全局应用程序上下文来保存值。这些可在数据库会话之间访问(因此您需要注意标识符)。 Find out more

除此之外,请考虑内存变量(PL / SQL还是应用程序上下文)是否是安全的方法。如果要跟踪某些工作流程或流程状态,通常仅将其存储在表中会更好,这仅是出于恢复目的。

答案 1 :(得分:0)

您的过程周围都有数据库-如果您确实需要诸如过程内部某个块的执行计数之类的东西,只需创建专用表并在每次执行时对其进行更新。

如果您在单个事务范围内,会话范围内执行是继续执行,还是在整个执行过程中进行计数……