pl / sql - 比较2个用户表中的记录计数

时间:2011-09-13 12:07:43

标签: sql database oracle plsql count

我在架构'staff'下有'stf_table'表,用户名为'staff'。

我在架构'employee'下有'emp_table'表,用户名为'employee'。

这两个都在相同的数据库SID /主机/端口下,但用户'staff'没有查询架构'employee'下的表,反之亦然(即用户'employee'没有privelege到架构'staff'下的查询表。但是每个用户都可以在自己的架构下查询表。注意:我无法授予额外的权限,我不想将两个表都转储到本地模式中。

是否可以编写执行以下操作的PL / SQL proc或包?

 select count(*) from stf_table;
 select count(*) from emp_table;

然后将两个计数输出到一个文件(即.txt或.dat无关紧要),如下所示:

stf_table count: 47830
emp_table count: 36462
difference: 11368
counts match: FALSE

3 个答案:

答案 0 :(得分:8)

如果您不想为这两个用户授予其他权限,则没有多少选项。

您可以创建一个超级用户拥有的程序,比如一个具有SELECT ANY TABLE的帐户(但 SYS或SYSTEM),这两个计数都会计算并计算差异。

create function get_diff 
    return pls_integer
    authid definer
as 
    c1 pls_integer;
    c2 pls_integer;
begin
    select count(*) 
    into c1
    from staff.stf_table;
    select count(*)
    into c2
    from employee.emp_table;

    return abs(c1-c2);
end get_diff;
/

所以关键是AUTHID DEFINER。这意味着该函数以拥有该函数的用户的权限运行;因为他们有必要的权限来查询用户可以运行该函数的两个表,所以他们授予EXECUTE ON GET_DIFF的任何其他用户也是如此。

这真的是给予你可以逃脱的最低限度。


注意:我没有解决写入文件的问题,因为我并不认为这是你问题的主旨。主要是权限。


  

“没有办法将proc连接起来,因为用户'工作人员'保存了   数到一个文件。然后以用户'employee'连接将计数保存到   相同的文件和比较?“

没有。这不是安全模型的工作方式。

STAFF的数据归STAFF所有,EMPLOYEE的数据归EMPLOYEE所有。默认情况下,STAFF无法查看EMPLOYEE的数据,反之亦然。要改变这种情况,您有两种选择:

  1. 让STAFF在他们的桌子上授予对EMPLOYEE的SELECT,并让EMPLOYEE将他们的桌子上的SELECT授予STAFF。
  2. 使用对两个模式表都有特权的帐户来完成工作。
  3. 显然,第一种方法可能存在数据保护问题。如果您关心这一点,那么您可以进行一些改进:

    1. 让每个架构拥有一个只选择其记录计数的视图,并为视图授予权限。
    2. 如果您拥有Enterprise Edition 10gR2或更高版本,则可以使用列级VPD:表上的grant select将策略放置到位以隐藏所有敏感数据。 Find out more

答案 1 :(得分:1)

授予权限是正确的做法,但是你声明这是不可能的:

一种解决方案可以是使用脚本在命令行执行此操作。 (最大的缺点是用户名和密码将嵌入脚本中供所有人查看,因此请确保脚本得到适当保护)

首先创建2个脚本:

a.sql:

set timing off
set feedback off
set pages 0
select count(*) from stf_table;
exit

b.sql:

set timing off
set feedback off
set pages 0
select count(*) from emp_table;
exit

现在创建一个脚本文件extract.bat来获取输出:

 @echo off
 FOR /F "usebackq delims=!" %%i IN (`sqlplus -s username/password@db_a @a.sql`) DO set resulta=%%i 

 FOR /F "usebackq delims=!" %%i IN (`sqlplus -s username/password@db_b @b.sql`) DO set resultb=%%i 

 set /a diff=%resulta%-%resultb%

 echo stf_table count %resulta% 
 echo emp_table count %resultb%
 echo difference %diff%

 IF %diff%=0 (
 echo Counts match TRUE
 ) ELSE (
 echo Counts match FALSE)

现在只需在命令提示符下执行extract.bat

答案 2 :(得分:1)

APC是正确的,因为您无法在不授予其他权限的情况下轻松解决此问题。可能有一种比他建议的更简单的方式。

我建议创建一个视图并将该视图授予其他模式。

在STAFF架构中,您可以创建一个视图stf_table_count:

create or replace view stf_table_count
as
select count(*) as num_rows
from stf_count;

然后将该视图的select选择授予员工架构:

grant select on stf_table_count to employee;

然后,从员工架构中,您可以在不获取数据的情况下找到结果

select num_rows from staff.stf_table_count
union all
select count(*) from emp_table;

您还可以重复此过程以获取员工架构中的员工数量。

我不是Oracle数据库安全专家,因此您的里程可能会有所不同,但我认为它应该有效。