带有 IF-THEN-ELSE 的 Oracle 过程产生错误
Oracle Procedure with an IF-THEN-ELSE produces error
我在 Oracle 中创建了这个过程,以根据存储在营销 table 的等级列中的等级为用户分配角色。但是,当我 运行 它时,我得到了错误。
初始问题
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);
vn_grade:=
您需要为该行分配一个值,或者删除它。您不能将 IF 语句分配给数字变量。可能摆脱它,然后更改您的 IF 语句以查看光标的成绩。您还需要结束循环。
此外,您不能直接在 PL/SQL 代码块中执行授权。您必须为此使用立即执行语句。而且您必须告诉它您将角色授予谁。
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;
grant
是 DDL,因此不能直接在 PL/SQL 中使用。为了实现这一点,需要动态执行 DDL,使用 execute immediately
。此外,grant
始终要求您指定角色的接收者。结果将是这样的:
execute immediate 'GRANT ROLE admin_staff to ' || rec_cur_user_grade.username;
一个 ORA-00990: missing or invalid privilege
错误是相当自我描述的:过程的所有者没有必要的权限来执行该过程正在尝试的操作。
这里最有可能的罪魁祸首是角色:不能在过程中使用角色授予的权限。您应该采取的第一步是确保程序的所有者已被明确授予管理所涉及角色的权限。
我发现了一些会阻止它工作的东西:
- 在您的
FOR
语句之后,没有 LOOP
语句(这是错误所抱怨的)。在你的 DBMS_OUTPUT
. 之后也没有 END LOOP
vn_grade
后跟 :=
赋值运算符,但未向其赋值。
GRANT
语句被编写为裸 DDL,这在 PL/SQL 中是不允许的。它们需要包裹在 EXECUTE IMMEDIATE
. 中
grade
和 username
需要由游标变量限定(例如,rec_cur_user_grade.grade
和 rec_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;
/
我在 Oracle 中创建了这个过程,以根据存储在营销 table 的等级列中的等级为用户分配角色。但是,当我 运行 它时,我得到了错误。
初始问题
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);
vn_grade:=
您需要为该行分配一个值,或者删除它。您不能将 IF 语句分配给数字变量。可能摆脱它,然后更改您的 IF 语句以查看光标的成绩。您还需要结束循环。
此外,您不能直接在 PL/SQL 代码块中执行授权。您必须为此使用立即执行语句。而且您必须告诉它您将角色授予谁。
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;
grant
是 DDL,因此不能直接在 PL/SQL 中使用。为了实现这一点,需要动态执行 DDL,使用 execute immediately
。此外,grant
始终要求您指定角色的接收者。结果将是这样的:
execute immediate 'GRANT ROLE admin_staff to ' || rec_cur_user_grade.username;
一个 ORA-00990: missing or invalid privilege
错误是相当自我描述的:过程的所有者没有必要的权限来执行该过程正在尝试的操作。
这里最有可能的罪魁祸首是角色:不能在过程中使用角色授予的权限。您应该采取的第一步是确保程序的所有者已被明确授予管理所涉及角色的权限。
我发现了一些会阻止它工作的东西:
- 在您的
FOR
语句之后,没有LOOP
语句(这是错误所抱怨的)。在你的DBMS_OUTPUT
. 之后也没有 vn_grade
后跟:=
赋值运算符,但未向其赋值。GRANT
语句被编写为裸 DDL,这在 PL/SQL 中是不允许的。它们需要包裹在EXECUTE IMMEDIATE
. 中
grade
和username
需要由游标变量限定(例如,rec_cur_user_grade.grade
和rec_cur_user_grade.username
)。
END LOOP
尝试这样的事情(作为匿名块而不是过程运行,并使用隐式游标):
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;
/