使用IF-THEN-ELSE的Oracle过程会产生错误

时间:2015-02-19 14:20:38

标签: sql oracle if-statement procedure

我在Oracle中创建了此过程,根据营销表的成绩列中存储的成绩为用户分配角色。但是,当我运行它时,我会收到错误。

初始问题

CREATE OR REPLACE PROCEDURE proc_assign_role IS
    vn_grade NUMBER(5);

CURSOR cur_user_grade IS
    SELECT grade, username
    FROM marketing
    WHERE grade BETWEEN 1 AND 3;
BEGIN
    FOR rec_cur_user_grade IN cur_user_grade
    vn_grade:=
    IF grade= 1
        THEN 
            GRANT ROLE admin_staff;
        ELSIF grade= 2 THEN
            GRANT ROLE marketing_staff;
        ELSIF grade= 3 THEN
            GRANT ROLE event_staff;
    END IF;
    DBMS_OUTPUT.PUT_LINE(username||'YOU ARE A GRADE '||vn_grade|| 'USER');
END proc_assign_role;
/

这是我得到的错误:

ERROR at line 11: PLS-00103: Encountered the symbol "VN_GRADE" when expecting one of the following:

   . ( * @ % & - + / at loop mod remainder range rem ..
    || multiset
1. CREATE OR REPLACE PROCEDURE proc_assign_role IS
2.  vn_grade NUMBER(5); 

3 个答案:

答案 0 :(得分:2)

vn_grade:=

您需要为该行指定一个值,或者删除它。您不能将IF语句分配给数字变量。可能摆脱它,然后改变你的IF语句来查看光标的等级。你还需要结束循环。

此外,您无法直接在PL / SQL代码块中执行授权。您必须使用execute immediate语句。你必须告诉它你是谁给予了这个角色。

FOR rec_cur_user_grade IN cur_user_grade LOOP
    IF rec_cur_user_grade.grade= 1 THEN 
        execute immediate 'GRANT ROLE admin_staff to ' || rec_cur_user_grade.username;
    ELSIF rec_cur_user_grade.grade= 2 THEN
        execute immediate 'GRANT ROLE marketing_staff to ' || rec_cur_user_grade.username;
    ELSIF rec_cur_user_grade.grade= 3 THEN
        execute immediate 'GRANT ROLE event_staff to ' || rec_cur_user_grade.username;
    END IF;
DBMS_OUTPUT.PUT_LINE(username||'YOU ARE A GRADE '||rec_cur_user_grade.grade|| 'USER');
END LOOP;

答案 1 :(得分:1)

我看到一些可以防止这种情况发生的事情:

  • 在您的FOR语句之后,没有LOOP语句(错误是抱怨的)。 END LOOP之后也没有DBMS_OUTPUT
  • vn_grade之后是:=赋值运算符,但没有赋值给它。
  • GRANT语句写为裸DDL,PL / SQL中不允许这样做。它们需要包含在EXECUTE IMMEDIATE
  • gradeusername需要通过游标变量进行限定(例如rec_cur_user_grade.graderec_cur_user_grade.username)。

尝试这样的事情(作为匿名块运行,而不是程序,并使用隐式游标):

BEGIN
    FOR rec_cur_user_grade IN (
        SELECT grade, username
        FROM marketing
        WHERE grade BETWEEN 1 AND 3
    )
    LOOP
        CASE rec_cur_user_grade.grade
            WHEN 1 THEN
                EXECUTE IMMEDIATE 'GRANT ROLE admin_staff TO ' || rec_cur_user_grade.username;
            WHEN 2 THEN
                EXECUTE IMMEDIATE 'GRANT ROLE marketing_staff TO ' || rec_cur_user_grade.username;
            WHEN 3 THEN
                EXECUTE IMMEDIATE 'GRANT ROLE event_staff TO ' || rec_cur_user_grade.username;
        END CASE;
        DMBS_OUTPUT.PUT_LINE(rec_cur_user_grade.username || ' YOU ARE A GRADE ' || rec_cur_user_grade.grade || ' USER');
    END LOOP;
END;
/

答案 2 :(得分:0)

grant是DDL,因此无法直接在PL / SQL中使用。为了实现这一点,需要使用execute immediately动态执行DDL。此外,grant始终要求您指定角色的收件人。结果将是这样的:

execute immediate 'GRANT ROLE admin_staff to ' || rec_cur_user_grade.username;

ORA-00990: missing or invalid privilege错误相当自我描述:过程的所有者没有必要的权限来执行过程尝试的操作。

这里最可能的罪魁祸首是角色:角色授予的权限不能在过程中使用。您应该采取的第一步是确保已明确授予该过程的所有者管理所涉及角色的权限。