英文:
How to solve this trigger error while trying to insert? oracle sql
问题
I have a sp and a trigger, the trigger is supposed to call the procedure after I insert into the users table so I can create a new session user, but when I try to insert, I get the following errors:
- ORA-04092: cannot COMMIT in a trigger ORA-06512: at "SQL_VNNKBUUOCEZLLPHWSSGEFNOQE.CREAR_USUARIO", line 10
- ORA-06512: at "SQL_VNNKBUUOCEZLLPHWSSGEFNOQE.TRG_INSERT_USUARIO", line 2
- ORA-06512: at "SYS.DBMS_SQL", line 1721
This is my sql code:
CREATE OR REPLACE PROCEDURE crear_usuario(
p_nombre_de_usuario IN VARCHAR2,
p_correo IN VARCHAR2,
p_contrasenia IN VARCHAR2
)
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE USER ' || p_nombre_de_usuario || ' IDENTIFIED BY ' || p_contrasenia;
END;
CREATE OR REPLACE TRIGGER trg_insert_usuario
AFTER INSERT ON usuario
FOR EACH ROW
BEGIN
crear_usuario(:NEW.nombre_de_usuario, :NEW.correo, :NEW.contrasenia);
END;
The weird thing is that I don't have any commit.
英文:
I have a sp and a trigger, the trigger is supposed to call the procedure after I insert into the users table so I can create a new session user, but when I try to insert, I get the following errors:
- ORA-04092: cannot COMMIT in a trigger ORA-06512: at "SQL_VNNKBUUOCEZLLPHWSSGEFNOQE.CREAR_USUARIO", line 10
- ORA-06512: at "SQL_VNNKBUUOCEZLLPHWSSGEFNOQE.TRG_INSERT_USUARIO", line 2
- ORA-06512: at "SYS.DBMS_SQL", line 1721
This is my sql code:
CREATE OR REPLACE PROCEDURE crear_usuario(
p_nombre_de_usuario IN VARCHAR2,
p_correo IN VARCHAR2,
p_contrasenia IN VARCHAR2
)
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE USER ' || p_nombre_de_usuario || ' IDENTIFIED BY ' || p_contrasenia;
END;
CREATE OR REPLACE TRIGGER trg_insert_usuario
AFTER INSERT ON usuario
FOR EACH ROW
BEGIN
crear_usuario(:NEW.nombre_de_usuario, :NEW.correo, :NEW.contrasenia);
END;
The weird thing is that I don't have any commit
答案1
得分: 1
从我的角度来看,你应该在这种情况下避免使用触发器。应该将所有操作都放在存储过程中。
顺便说一下,在触发器中会触发提交是什么原因:触发器是由DDL语句触发的,它会在DDL语句之前和之后执行隐式提交。
你能在触发器中执行提交吗?当然可以,如果你将它设置为自主事务,但正如我所说,我不建议这样做。
这是一个可能的示例;代码应该由具有不太常见权限的用户运行 - create user
。
包含用户的表:当然,将密码存储为明文是明显错误的做法,但这只是一个简单的示例。
SQL> create table users
2 (user_id number generated always as identity primary key,
3 username varchar2(30) unique,
4 password varchar2(30)
5 );
Table created.
存储过程:如果表中不存在行,则将一行插入表中,如果插入了行,则创建用户:
SQL> create or replace procedure p_create_user
2 (p_username in varchar2,
3 p_password in varchar2
4 ) as
5 begin
6 insert into users (username, password)
7 select p_username, p_password
8 from dual
9 where not exists (select null
10 from users u
11 where u.username = p_username
12 );
13 if sql%rowcount = 1 then
14 execute immediate 'create user ' || p_username || ' identified by ' || p_password;
15 end if;
16 end;
17 /
Procedure created.
让我们来试试:
SQL> exec p_create_user('littlefoot', 'whatever');
PL/SQL procedure successfully completed.
SQL> select * From users;
USER_ID USERNAME PASSWORD
---------- ------------------------------ ------------------------------
1 littlefoot whatever
我可以再次插入相同的用户吗?不行:
SQL> exec p_create_user('littlefoot', 'whatever');
PL/SQL procedure successfully completed.
SQL> select * From users;
USER_ID USERNAME PASSWORD
---------- ------------------------------ ------------------------------
1 littlefoot whatever
不同的用户呢?
SQL> exec p_create_user('bigfoot', 'whatever');
PL/SQL procedure successfully completed.
SQL> select * From users;
USER_ID USERNAME PASSWORD
---------- ------------------------------ ------------------------------
1 littlefoot whatever
2 bigfoot whatever
如果我尝试以新创建的用户身份连接会发生什么:
SQL> connect littlefoot/whatever@pdb1
ERROR:
ORA-01045: user LITTLEFOOT lacks CREATE SESSION privilege; logon denied
Warning: You are no longer connected to ORACLE.
SQL>
显然,仅仅创建用户是不够的。用户存在,但不能执行任何操作。我想你以后会处理这个问题。
英文:
From my point of view, you should avoid trigger in this scenario. Do everything in a stored procedure.
BTW, what caused commit in a trigger: it was a DDL, it performs implicit commit right before and right after the DDL statement.
Can you commit in a trigger at all? Sure you can, if you make it an autonomous transaction, but - as I said - I wouldn't do that.
Here's an example of what you might do; code should be ran by user who has privilege that isn't that common - create user
.
Table that contains users: of course, storing passwords as plain text is plain wrong, but that's just a simple example.
SQL> create table users
2 (user_id number generated always as identity primary key,
3 username varchar2(30) unique,
4 password varchar2(30)
5 );
Table created.
Procedure: inserts a row into the table if it doesn't exist, and - if row was inserted - creates user:
SQL> create or replace procedure p_create_user
2 (p_username in varchar2,
3 p_password in varchar2
4 ) as
5 begin
6 insert into users (username, password)
7 select p_username, p_password
8 from dual
9 where not exists (select null
10 from users u
11 where u.username = p_username
12 );
13 if sql%rowcount = 1 then
14 execute immediate 'create user ' || p_username || ' identified by ' || p_password;
15 end if;
16 end;
17 /
Procedure created.
Let's try it:
SQL> exec p_create_user('littlefoot', 'whatever');
PL/SQL procedure successfully completed.
SQL> select * From users;
USER_ID USERNAME PASSWORD
---------- ------------------------------ ------------------------------
1 littlefoot whatever
Can I insert the same user again? No:
SQL> exec p_create_user('littlefoot', 'whatever');
PL/SQL procedure successfully completed.
SQL> select * From users;
USER_ID USERNAME PASSWORD
---------- ------------------------------ ------------------------------
1 littlefoot whatever
A different user?
SQL> exec p_create_user('bigfoot', 'whatever');
PL/SQL procedure successfully completed.
SQL> select * From users;
USER_ID USERNAME PASSWORD
---------- ------------------------------ ------------------------------
1 littlefoot whatever
2 bigfoot whatever
What if I try to connect as newly created user:
SQL> connect littlefoot/whatever@pdb1
ERROR:
ORA-01045: user LITTLEFOOT lacks CREATE SESSION privilege; logon denied
Warning: You are no longer connected to ORACLE.
SQL>
Apparently, creating user isn't enough. It exists, but can't do anything. I presume you'll handle that later.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论