Oracle Procedure - 返回所有行

时间:2014-02-20 18:45:28

标签: sql oracle plsql

所以我有几个表,我已经创建了不同的角色来与不同的用户一起使用,这样每个人都可以访问一部分表。

现在,每当我尝试SELECT * FROM yaser.enrol;与协调员打算查看所有内容时,我都会收到错误numeric or value error: character to number conversion error,该错误指向我正在查询employee_no的行确定员工角色。

Theres 4种类型的用户:学生,导师,讲师,协调员。

编辑** 添加了所有代码。

-- Create policy function to be called when ‘ENROL’ table is accessed under user Yaser.
create or replace function f_policy_enrol (schema in varchar2, tab in varchar2)

return varchar2
as
  v_emp_no            varchar2(10);
  v_student_no        varchar2(10);
  v_tutor_emp_no      varchar2(10);
  v_lecturer_emp_no   varchar2(10); 
  v_coord_emp_no      varchar2(10);
  is_tutor            number:=0;
  is_lecturer         number:=0;
  is_coordinator      number:=0;
  is_student          number:=0;
  is_employee         number:=0;
  v_program_code      varchar2(10);
  v_user              varchar2(100);
  out_string          varchar2(400) default '1=2 ';
 -- The return value will be out_string. '1=2' means 'Nothing to access'. 

begin
  -- get session user
  v_user := lower(sys_context('userenv','session_user'));

  -- Is the user a student?
  begin
    SELECT student_no INTO v_student_no FROM student WHERE lower(student_no) = v_user;
    is_student:=1;
  exception
    when no_data_found then
    v_student_no := 0;
  end;

  -- Is the user an employee?
  begin
    SELECT emp_no INTO v_emp_no FROM employee WHERE lower(emp_no) = v_user;
    is_employee:=1;
  exception
    when no_data_found then
    v_emp_no := 0;
  end;

  -- Query the employee number to determine role. 
  -- If Tutor.
  SELECT MAX(tutor_emp_no) INTO v_tutor_emp_no FROM tutorial WHERE lower(tutor_emp_no) = v_user;
  -- If Lecturer.
  SELECT MAX(course_coord_emp_no) INTO v_lecturer_emp_no FROM course WHERE lower(course_coord_emp_no) = v_user;
  -- If Coordinator.
  SELECT MAX(prog_coord_emp_no) into v_coord_emp_no FROM program WHERE lower(prog_coord_emp_no) = v_user;

  -- Get role of the employee if the user is an employee.
  if v_emp_no != 0 and v_tutor_emp_no is NOT NULL then
     -- Employee is a Tutor.
     is_tutor := 1;
  elsif v_emp_no != 0 and v_lecturer_emp_no is NOT NULL then
     -- Employee is Lecturer.
     is_lecturer := 1;
  elsif v_emp_no != 0 and v_coord_emp_no is NOT NULL then
     -- Employee is Coordinator.
     is_coordinator := 1;
  end if;

  -- Create the string to be used as the WHERE clause.
  if is_student = 1 then
     -- Students are allowed to see their orders only.
     out_string := out_string||'or student_no = '''||v_student_no||''' ';
  end if;

  if is_tutor = 1 then
     -- Tutors are allowed to see enrolments of students that they tutor.
----     out_string := out_string||'or student_no in (select student_no from tutorial where tutor_emp_no = '||v_tutor_emp_no||') ';
---- NOT WORKING.
     out_string := out_string||'or student_no in (select student_no from tutorial where lower(tutor_emp_no) = v_tutor_emp_no) ';

  end if;

  if is_coordinator = 1 then
     -- The coordinator is allowed to see all records in ENROL (WHERE 1=1 or anything) means all rows.
     out_string := out_string||'or 1=1 ';
  end if;

  return out_string;
end;
/

这些是我正在引用的表格:

CREATE TABLE course
(
    course_code varchar(10),
    course_title varchar(50),
    course_coord_emp_no varchar(10),
    primary key (course_code)
);

并且 - 所有员工:

CREATE TABLE employee
(
    emp_no varchar(10),
    name   varchar(100)
);

所有其他表格基本相同 - VARCHARS

任何帮助都会很好! :) 亚瑟

1 个答案:

答案 0 :(得分:1)

这个问题已经发展了一个很多,这个答案的大部分内容都是关于与您的实际代码无关的遗失end if。实际上回到你的原始问题,使用or 1=1作为一个包罗万象是好的,即使if的另一个分支如果比较字符串 - 它没有区别一点都不如果你真的想比较字符串,你可以做同样的事情:

'or ''x''=''x'' '

......或

'or v_user=v_user '

但是你无法比较你在评论中显示的空字符串。空字符串''与Oracle中的null相同,您无法将任何内容等同于null,甚至本身。 (如果v_usernull,则上一次检查将失败,原因相同)。另一种可能性是:

'or null is null '

请注意,此处的比较器为is,而不是=

其中没有一个解决了为什么你会得到VPD错误,因为所有这些都是等效的 - 它们总是评估为真,并且你使用哪个并不重要。任何有效结束为or true的东西都会完全相同;只是遗憾的是Oracle SQL不理解这样的布尔值。在任何其他子句中进行比较的数据类型与此子句无关。

在这两种情况下,您需要查看函数实际返回的内容,验证它是您所期望的,并在查询VPD直接反对的表时验证它是否作为限制。