Oracle PL/SQL:如何声明会话变量?
如何在PL/SQL中声明会话变量?该变量仅在会话期间保持不变,而不必将其存储在数据库中?您可以创建一个包级变量。这是一个简单的例子:Oracle PL/SQL:如何声明会话变量?,oracle,plsql,Oracle,Plsql,如何在PL/SQL中声明会话变量?该变量仅在会话期间保持不变,而不必将其存储在数据库中?您可以创建一个包级变量。这是一个简单的例子: CREATE OR REPLACE PACKAGE my_package AS FUNCTION get_a RETURN NUMBER; END my_package; / CREATE OR REPLACE PACKAGE BODY my_package AS a NUMBER(20); FUNCTION get_a RE
CREATE OR REPLACE PACKAGE my_package
AS
FUNCTION get_a RETURN NUMBER;
END my_package;
/
CREATE OR REPLACE PACKAGE BODY my_package
AS
a NUMBER(20);
FUNCTION get_a
RETURN NUMBER
IS
BEGIN
RETURN a;
END get_a;
END my_package;
/
如果您这样做,您应该仔细阅读(并正确处理)ORA-04068
错误。每个数据库会话都有它自己的值。您可以尝试以下方法:
SELECT my_package.get_a FROM DUAL;
您可以使用“用户创建的上下文”来存储会话中跨多个单元共享的数据 首先,创建一个上下文:
CREATE CONTEXT SYS_CONTEXT ('userenv', 'current_schema')|| '_ctx' USING PKG_COMMON
其次,创建一个包来管理您的上下文:
CREATE OR REPLACE PACKAGE PKG_COMMON
IS
common_ctx_name CONSTANT VARCHAR2 (60)
:= SYS_CONTEXT ('userenv', 'current_schema')
|| '_ctx';
FUNCTION fcn_get_context_name RETURN VARCHAR2;
PROCEDURE prc_set_context_value (var_name VARCHAR2, var_value NUMBER);
END;
CREATE OR REPLACE PACKAGE BODY PKG_COMMON
IS
FUNCTION fcn_get_context_name
RETURN VARCHAR2
IS
BEGIN
RETURN common_ctx_name;
END;
PROCEDURE prc_set_context_value (var_name VARCHAR2, var_value NUMBER)
IS
BEGIN
DBMS_SESSION.set_context (common_ctx_name, var_name, var_value);
END;
END;
prc_set_context_值可以更高级,这只是一个示例。
创建了上下文和包之后,就可以开始使用它们了。
使用过程调用设置上下文变量
begin
PKG_COMMON.prc_set_context_value('MyVariable', 9000)
end;
并在任何地方使用它-任何过程、包、函数或事件视图
CREATE VIEW V_TEST AS
SELECT ID, LOGIN, NAME
FROM USERS
WHERE ROLE_ID = SYS_CONTEXT(PKG_COMMON.FCN_GET_CONTEXT_NAME, 'MyVariable')
有关更多信息,请参见我喜欢使用简短但直观的语法,因此会创建一些
ctx
包,这些包只提供一个函数来设置和获取一些全局“变量”(仅对当前会话有效;在我的情况下,不需要将其作为用户创建的上下文变量实现,但可以在引擎盖下轻松地对其进行更改;例如,使用一些
foo varchar2
和bar number
vars)
用法:
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'
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;
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;
包头:
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'
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;
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;
包体:
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'
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;
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;
如果您知道变量(foo
)可能在单个查询中发生更改,请删除parallel\u enable
,否则,如果查询是可并行的,则会更有效
根据需要,当然可以添加一些
foo_reset()
将其设置为null等。当我创建上下文时,它会说:ORA-28265:不允许以“sys_”开头的命名空间。我试着把它设置为变量。但是它设置变量名而不是值为什么使用CURRENT_SCHEMA
动态构建上下文名?它需要全局唯一还是什么?我假设您需要一个过程来设置值?@jpmc26有一个setter是正常的。我认为可以将变量放入包中(而不是包体)以使其公开。