我有一个名为 Tamaris 的数据库,其中包含一个表 User。我创建了一个触发器,以便每次在用户表中插入一行时在数据库中创建一个新用户。这是 PL/SQL 代码:
CREATE OR REPLACE
TRIGGER UTILISATEUR_CREATE_USER_TRG
AFTER INSERT ON UTILISATEUR
FOR EACH ROW
DECLARE
nom_compte NVARCHAR2(20 CHAR);
str_create VARCHAR2(300);
str_grant VARCHAR(250);
type_compte NUMBER;
unauthorized_exception EXCEPTION;
BEGIN
CASE
WHEN :new.idtypecompte = 1 THEN
nom_compte := :new.pseudoutilisateur;
type_compte := 1;
WHEN :new.idtypecompte = 2 THEN
nom_compte := 'AC_'|| :new.pseudoutilisateur;
type_compte := 2;
WHEN :new.idtypecompte = 3 THEN
RAISE unauthorized_exception;
END CASE;
str_create := 'CREATE USER '|| nom_compte ||' IDENTIFIED BY '|| :new.passwordutilisateur ||' DEFAULT TABLESPACE tamaris TEMPORARY TABLESPACE temp QUOTA UNLIMITED ON tamaris;' ;
EXECUTE IMMEDIATE str_create;
IF type_compte = 1 THEN
str_grant := 'GRANT Base_User TO '|| nom_compte ||';' ;
EXECUTE IMMEDIATE str_grant;
ELSE
str_grant := 'GRANT Adv_User TO '|| nom_compte ||';' ;
EXECUTE IMMEDIATE str_grant;
END IF;
EXCEPTION
WHEN unauthorized_exception THEN
dbms_output.put_line('Impossible de créer un autre gestionnaire');
END;
当我在表 User 中插入一行时,触发器会触发,我得到:
保存对“TAMARIS”.“UTILISATEUR”的修改时出错: 第 3 行:ORA-00911:无效字符 ORA-06512: 在“TAMARIS.UTILISATEUR_CREATE_USER_TRG”,第 22 行 ORA-04088: 执行“TAMARIS.UTILISATEUR_CREATE_USER_TRG”时出错 ORA-06512: 在第 1 行
根据记录,str_create 中的请求在带有随机参数的触发器之外工作(仅当用 BEGIN; END; 包装时)。因此我尝试了:
str_create := 'BEGIN CREATE USER '|| nom_compte ||' IDENTIFIED BY '|| :new.passwordutilisateur ||' DEFAULT TABLESPACE tamaris TEMPORARY TABLESPACE temp QUOTA UNLIMITED ON tamaris; END;' ;
仍然无法工作。如果有任何意见,我将不胜感激,谢谢。
编辑:
建议的程序内容:
CREATE OR REPLACE
PROCEDURE CREATE_USER_IN_DB(p_username IN NVARCHAR2, p_password IN UTILISATEUR.passwordutilisateur%type, p_type IN NUMBER ) AS
BEGIN
EXECUTE IMMEDIATE 'CREATE USER '|| p_username ||' IDENTIFIED BY '|| p_password ||' DEFAULT TABLESPACE tamaris
TEMPORARY TABLESPACE temp QUOTA UNLIMITED ON tamaris';
IF p_type = 1 THEN
EXECUTE IMMEDIATE 'GRANT Base_User TO '|| p_username;
ELSE
EXECUTE IMMEDIATE 'GRANT Adv_User TO '|| p_username;
END IF;
END CREATE_USER_IN_DB;
编辑2:
我如何在触发器之外调用该过程:
BEGIN
CREATE_USER_IN_DB('whatever','quickpass', 2);
END;
我明白
ORA-00900:
Invalid SQL instruction
ORA-06512: at "TAMARIS.CREATE_USER_IN_DB", line 3
ORA-06512: at line 2
00900. 00000 - "invalid SQL statement"
*Cause:
*Action:
最佳答案
1) 正如 @Bob Jarvis 所建议的,当您构建要传递给 EXECUTE IMMEDIATE
的 SQL 语句时,该 SQL 语句不应包含尾随分号 ;
2) 由于CREATE USER
和GRANT
是DDL 语句,因此它们在执行之前和之后都会发出隐式提交。这意味着您不能在触发器中调用 DDL 语句,因为触发器不能导致事务结束。如果您确实想这样做(并且创建用户作为在表中插入行的副作用似乎是一个非常有问题的体系结构),则必须异步执行此操作。您的触发器可以调用 DBMS_JOB 来安排作业在当前事务完成后运行,并且该作业可以执行 DDL 语句。例如,如果您创建一个实际创建用户的过程(这是所有 DDL 所在的位置)
CREATE PROCEDURE create_user( p_username IN NVARCHAR2,
p_password IN UTILISATEUR.passwordutilisateur%type,
p_type IN NUMBER )
AS
<<implement procedure>>
那么你的触发器可以做类似的事情
CREATE OR REPLACE
TRIGGER UTILISATEUR_CREATE_USER_TRG
AFTER INSERT ON UTILISATEUR
FOR EACH ROW
DECLARE
nom_compte NVARCHAR2(20 CHAR);
str_create VARCHAR2(300);
str_grant VARCHAR(250);
type_compte NUMBER;
l_jobno PLS_INTEGER;
unauthorized_exception EXCEPTION;
BEGIN
CASE
WHEN :new.idtypecompte = 1 THEN
nom_compte := :new.pseudoutilisateur;
type_compte := 1;
WHEN :new.idtypecompte = 2 THEN
nom_compte := 'AC_'|| :new.pseudoutilisateur;
type_compte := 2;
WHEN :new.idtypecompte = 3 THEN
RAISE unauthorized_exception;
END CASE;
dbms_job.submit( l_jobno,
'BEGIN create_user( ''' || nom_compte || ''', ' ||
'''' || :new.passwordutilisateur || ''', ' ||
type_compte || '); END;' );
END;
关于oracle - 动态 SQL 和 ORA-00911,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11249878/