Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Oracle VPD“设置上下文”不工作_Sql_Oracle_Database Administration - Fatal编程技术网

Sql Oracle VPD“设置上下文”不工作

Sql Oracle VPD“设置上下文”不工作,sql,oracle,database-administration,Sql,Oracle,Database Administration,我已经编写了一个VPD,其中有管理员用户,比如JAdmin,PAdmin,属于company_ID=90,FAdmin,KAdmin属于company_ID=91。在Employee表中还有属于这两家公司的其他员工。还有其他表包含来自两家公司的信息,如时间表、工资单周期等。还有一个名为Company_Administrators的表,其中包含管理员及其公司ID的列表。目标是使用Set_Context获取登录时管理员的公司ID,并使用它仅显示来自其公司的信息。守则: CREATE USER JAd

我已经编写了一个VPD,其中有管理员用户,比如JAdmin,PAdmin,属于company_ID=90,FAdmin,KAdmin属于company_ID=91。在Employee表中还有属于这两家公司的其他员工。还有其他表包含来自两家公司的信息,如时间表、工资单周期等。还有一个名为Company_Administrators的表,其中包含管理员及其公司ID的列表。目标是使用Set_Context获取登录时管理员的公司ID,并使用它仅显示来自其公司的信息。守则:

CREATE USER JAdmin IDENTIFIED BY JAdmin
DEFAULT TABLESPACE IA643_TBS
TEMPORARY TABLESPACE TEMP
ACCOUNT UNLOCK;

CREATE USER FAdmin IDENTIFIED BY FAdmin
DEFAULT TABLESPACE IA643_TBS
TEMPORARY TABLESPACE TEMP
ACCOUNT UNLOCK;

CREATE USER PAdmin IDENTIFIED BY PAdmin
DEFAULT TABLESPACE IA643_TBS
TEMPORARY TABLESPACE TEMP
ACCOUNT UNLOCK;

CREATE USER KAdmin IDENTIFIED BY KAdmin
DEFAULT TABLESPACE IA643_TBS
TEMPORARY TABLESPACE TEMP
ACCOUNT UNLOCK;

GRANT CONNECT, RESOURCE TO JAdmin;
GRANT CONNECT, RESOURCE TO FAdmin;
GRANT CONNECT, RESOURCE TO PAdmin;
GRANT CONNECT, RESOURCE TO KAdmin;

CREATE OR REPLACE PUBLIC SYNONYM COMPANY 
FOR DBA643.COMPANY;
GRANT INSERT, SELECT, UPDATE, DELETE ON COMPANY 
TO FAdmin, JAdmin, PAdmin, KAdmin;

CREATE OR REPLACE PUBLIC SYNONYM EMPLOYEE 
FOR DBA643.EMPLOYEE;
GRANT INSERT, SELECT, UPDATE, DELETE ON EMPLOYEE 
TO FAdmin, JAdmin, PAdmin, KAdmin;

CREATE OR REPLACE PUBLIC SYNONYM TIMESHEET 
FOR DBA643.TIMESHEET;
GRANT INSERT, SELECT, UPDATE, DELETE ON TIMESHEET 
TO FAdmin, JAdmin, PAdmin, KAdmin;

CREATE OR REPLACE PUBLIC SYNONYM PAYROLL_PERIOD 
FOR DBA643.PAYROLL_PERIOD;
GRANT INSERT, SELECT, UPDATE, DELETE ON PAYROLL_PERIOD 
TO FAdmin, JAdmin, PAdmin, KAdmin;

CREATE OR REPLACE PUBLIC SYNONYM DAILY_WORK_HOURS 
FOR DBA643.DAILY_WORK_HOURS;
GRANT INSERT, SELECT, UPDATE, DELETE ON DAILY_WORK_HOURS 
TO FAdmin, JAdmin, PAdmin, KAdmin;


Conn sys as sysdba

CREATE USER sysadmin_ctx IDENTIFIED BY secAdmin;
GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER
DATABASE TRIGGER TO sysadmin_ctx IDENTIFIED BY secAdmin;
GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
GRANT EXECUTE ON DBMS_RLS TO sysadmin_ctx;
GRANT RESOURCE TO sysadmin_ctx;

GRANT SELECT ON Company_Administrators TO sysadmin_ctx; 


CREATE OR REPLACE CONTEXT Company_Admin USING PKG_Comp_Admin;
CREATE OR REPLACE PACKAGE PKG_Comp_Admin IS
PROCEDURE Get_Company_ID;
END;
/
CREATE OR REPLACE PACKAGE BODY PKG_Comp_Admin IS
PROCEDURE Get_Company_ID IS
V_Company_ID NUMBER;
BEGIN
    SELECT Company_ID
    INTO V_Company_ID
    FROM DBA643.Company_Administrators
    WHERE System_Username = SYS_CONTEXT('USERENV', 'SESSION_USER');
    DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', 'V_Company_ID');
    EXCEPTION
    WHEN NO_DATA_FOUND THEN NULL;
    END;
END;
/
SHOW ERROR;



CREATE OR REPLACE FUNCTION Company_Admin_fun (P_schema_name IN varchar2, 
P_object_name IN varchar2) RETURN varchar2 IS
V_where varchar2(300);
BEGIN
    IF User = 'DBA643' then
    V_where := '';
ELSE
    V_where := 'Company_ID = '||NVL(SYS_CONTEXT('Company_Admin', 'CompanyID'),0);
    END IF;
RETURN V_where;
END;
/


EXEC DBMS_RLS.DROP_Policy ('DBA643','COMPANY','COMPANY_POLICY');
EXEC DBMS_RLS.DROP_Policy ('DBA643','EMPLOYEE','EMPLOYEE_POLICY');
EXEC DBMS_RLS.DROP_Policy ('DBA643','TIMESHEET','TIMESHEET_POLICY');
EXEC DBMS_RLS.DROP_Policy ('DBA643','DAILY_WORK_HOURS','DAILY_WORK_HOURS_POLICY');


EXEC DBMS_RLS.ADD_Policy ('DBA643','COMPANY','COMPANY_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE);
EXEC DBMS_RLS.ADD_Policy ('DBA643','EMPLOYEE','EMPLOYEE_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE);
EXEC DBMS_RLS.ADD_Policy ('DBA643','TIMESHEET','TIMESHEET_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE);
EXEC DBMS_RLS.ADD_Policy ('DBA643','DAILY_WORK_HOURS','DAILY_WORK_HOURS_POLICY','sysadmin_ctx','Company_Admin_fun','SELECT, UPDATE, DELETE, INSERT', TRUE);


CREATE OR REPLACE TRIGGER After_Logon_Trigger
AFTER LOGON
ON DATABASE
BEGIN
    sysadmin_ctx.PKG_Comp_Admin.Get_Company_ID;
END;
/
当我以管理员的身份登录并执行select查询时,我得到“未选择行”。我想我已经把问题缩小到Set_context部分,因为当我作为管理员之一登录后使用以下命令时,它不会在Company_Admin context中显示更新后的值,而Company_Admin context应该是管理员的Company ID

select SYS_CONTEXT('Company_Admin', 'CompanyID') from dual

任何帮助都将不胜感激。多谢各位

您将上下文设置为错误的值—文字字符串V_Company_ID,而不是变量值—而不是

DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', 'V_Company_ID');
应该是

DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', V_Company_ID);
关于调试的进一步建议:

在sysadmin\u ctx.PKG\u Comp\u Admin.Get\u Company\u ID过程中编写一个记录用户日志的日志条目 如果您使用的是Oracle 12c:请使用dbms_实用程序.expand_sql_text查看VPD附加到原始sql语句中的内容
您将上下文设置为错误的值—文字字符串V_Company_ID,而不是变量值—而不是

DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', 'V_Company_ID');
应该是

DBMS_SESSION.SET_CONTEXT('COMPANY_ADMIN', 'CompanyID', V_Company_ID);
关于调试的进一步建议:

在sysadmin\u ctx.PKG\u Comp\u Admin.Get\u Company\u ID过程中编写一个记录用户日志的日志条目 如果您使用的是Oracle 12c:请使用dbms_实用程序.expand_sql_text查看VPD附加到原始sql语句中的内容
您是否尝试过使用accessglobally子句创建上下文

如果set_context操作在与查询上下文名称空间的会话不同的会话上运行,则不会得到任何数据。 不使用ACCESSED GLOBALLY子句创建的上下文将仅在会话级别保存数据。当使用accessedsglobally子句创建它时,可以在实例级别访问数据

附言

我认为没有办法在RAC级别上创建上下文,因为上下文将其数据保存在服务器的RAM上,至少在11gR2上没有已知选项将上下文的数据复制到每个RAC节点。
此外,依赖上下文也是有问题的,因为如果计划将数据用作经典全局变量或全局计数器,则在实例关闭时无法保存数据。命名空间的数据应在每次实例启动时设置。

是否尝试使用ACCESSED global子句创建上下文

如果set_context操作在与查询上下文名称空间的会话不同的会话上运行,则不会得到任何数据。 不使用ACCESSED GLOBALLY子句创建的上下文将仅在会话级别保存数据。当使用accessedsglobally子句创建它时,可以在实例级别访问数据

附言

我认为没有办法在RAC级别上创建上下文,因为上下文将其数据保存在服务器的RAM上,至少在11gR2上没有已知选项将上下文的数据复制到每个RAC节点。
此外,依赖上下文也是有问题的,因为如果计划将数据用作经典全局变量或全局计数器,则在实例关闭时无法保存数据-命名空间的数据应在每次实例启动时设置。

谢谢Frank,我试过了,我也试过用一个静态值代替V_Company_ID,但仍然有同样的问题。我还发现管理员用户不会与我在sysadmin_ctx用户下创建的任何上下文相关联。因此,set_上下文可以工作,但我的管理员用户不会与之关联。谢谢Frank,我确实尝试过,我也尝试过使用静态值而不是V_Company_ID,但仍然存在相同的问题。我还发现管理员用户不会与我在sysadmin_ctx用户下创建的任何上下文相关联。因此,set_上下文可以工作,但我的管理员用户不会与之关联。请添加VPD作为标记。Oracle VPD是指Oracle中的虚拟专用数据库。请添加VPD作为标记。Oracle VPD是指Oracle中的虚拟专用数据库。