PL/SQL: How do I declare session variables?

前端 未结 3 534
眼角桃花
眼角桃花 2021-02-04 05:18

How do I declare a session variable in PL/SQL - one that will persist for the duration of the session only, without me having to store it in the database itself?

3条回答
  •  一生所求
    2021-02-04 05:36

    I like to use a short, but intuitive syntax and thus would create e.g. some ctx package that just provides one function to set and get some global "variables".
    (valid for the current session only ; in my case no need to implement it as user-created-context variables, but easily changeable to it under the hood ; example with some foo varchar2 and bar number vars)

    usage:

    select ctx.foo from dual                                                 -- => null (init)
    select ctx.foo('a') from dual                                            -- => 'a'
    select ctx.foo('b') from dual ; select ctx.foo from dual                 -- => 'b', 'b'
    

    .

    -- (optimizer should cause the subquerys unselected columns not to be executed:)
    select 'ups' from (select ctx.foo('a') from dual) ; select ctx.foo from dual   -- => null
    
    select ctx.bar(1.5) from dual ; select ctx.bar from dual                 -- => 1.5,  1.5
    -- ...
    

    package header:

    create or replace package  ctx  as
    
      -- select ctx.foo from dual                                            -- => null (init)
      -- select ctx.foo('a') from dual                                       -- => 'a'
      -- select ctx.foo('b') from dual ; select ctx.foo from dual            -- => 'b', 'b'
      -- (optimizer should cause the subquerys unselected columns not to be executed:)
      -- select 'ups' from (select ctx.foo('a') from dual) ; select ctx.foo from dual
        -- => null
      -- parallel_enable for queries since it should not change inside of them
      function foo(  set varchar2 := null  ) return varchar2  parallel_enable;
    
      -- (samples like in foo above as executable test comments like in foo above skipped for 
      -- brevity)
      function bar(  set number := null  ) return  number  parallel_enable;
    
    end;
    

    package body:

    create or replace package body  ctx  as
    
      foo_  varchar2(30);  -- e.g. 'blabla'
      bar_  number;
    
    
      -- internal helper function for varchars
      function set_if_not_null( ref  in out  varchar2,  val  varchar2  ) return varchar2 as 
      begin
        if  val is not null  then  ref := val;  end if;
        return ref ;
      end;
    
    
      -- internal helper function for numbers
      function set_if_not_null( ref  in out  number,  val number  ) return  number  as begin
        if  val is not null  then  ref := val;  end if;
        return ref ;
      end;
    
    
      -- (same test comments like in foo above skipped for brevity)      
      function foo(  set varchar2 := null  ) return varchar2  parallel_enable as begin
        return set_if_not_null(  foo_,  set  ) ;
      end;
    
    
      -- (same test comments like in foo above skipped for brevity)      
      function bar(  set number := null  ) return  number  parallel_enable as begin
        return set_if_not_null(  bar_,  set  ) ;
      end;
    
    end;
    

    If you know that the variable (foo) may change within a single query then remove parallel_enable, which should otherwise be more performant if queries are parallelizable.

    Depending on ones needs one could of course add some foo_reset() to set it to null etc..

提交回复
热议问题