Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 我可以在触发器中创建用户吗?_Sql_Oracle_Plsql_Triggers - Fatal编程技术网

Sql 我可以在触发器中创建用户吗?

Sql 我可以在触发器中创建用户吗?,sql,oracle,plsql,triggers,Sql,Oracle,Plsql,Triggers,我想知道是否可以在触发器中创建一个用户。虽然我认为我的代码在语法上是正确的,但我还是有错误 这是密码 CREATE OR REPLACE TRIGGER addUser BEFORE INSERT ON PLSQL_TEST_USERS FOR EACH ROW DECLARE n VARCHAR2(20) := :new.name; p VARCHAR2(20) := :new.password; BEGIN dbms_output.put_line(n); EXECUTE I

我想知道是否可以在触发器中创建一个用户。虽然我认为我的代码在语法上是正确的,但我还是有错误

这是密码

CREATE OR REPLACE TRIGGER addUser
BEFORE INSERT
ON PLSQL_TEST_USERS
FOR EACH ROW
DECLARE
  n VARCHAR2(20) := :new.name;
  p VARCHAR2(20) := :new.password;
BEGIN
  dbms_output.put_line(n);
  EXECUTE IMMEDIATE ('CREATE USER n IDENTIFIED BY p');
END;
/
那么有可能做到这一点吗

以下是我得到的错误:

将用户值(1,‘rob’、‘asdf’)插入到PLSQL测试中
错误报告-
SQL错误:ORA-04092:无法在触发器中提交
ORA-06512:SYSTEM.ADDUSER第6行 ORA-04088:执行触发器“SYSTEM.ADDUSER”时出错
409200000-“不能在触发器中使用%s”
*原因:触发器试图提交或回滚。
*操作:重写触发器,使其不提交或回滚


不,您不能正确地执行此操作

不能在触发器内提交(通常,我将在下面讨论异常)。DDL-like
CREATE USER
发出两个隐式提交(一个在语句之前,一个在语句之后),因此不能将DDL放入触发器中

如果将触发器声明为使用自治事务,则会发生关于在触发器内提交的规则的异常。但这并不能正确地解决问题,原因有几个。首先,正如名字所说,自治事务是自治的,因此即使触发语句回滚,它也将被提交。这意味着,如果
INSERT
语句成功地插入了一行,但该更改被回滚,则自治事务将保持提交状态,这样您将在
plsql\u test\u users
表中创建一个用户,但没有任何行。出于写一致性的原因,Oracle还可能在内部回滚并重新执行一条语句,该语句将导致自治事务执行两次,第二次将失败,因为用户已经存在。自治事务实际上只应用于您希望记录信息的情况,无论基础更改是否成功(即记录尝试的登录或密码更改,以便即使不成功的登录或密码更改没有改变数据的状态,您也可以检测攻击)

您可以使用触发器调用dbms_job.submit来提交后台作业,该作业将在语句提交(如果确实提交)后不久运行,该语句将实际创建用户。这将在添加到表中的行和创建的用户之间产生一个小的延迟,但至少在事务上是正确的(延迟可能会增大,具体取决于您尝试创建的用户数量和允许的后台作业数量)。不幸的是,您必须使用较旧的
dbms\u作业
包而不是较新的
dbms\u调度程序
包来提交作业,因为较新的包包含隐式提交

如果您选择后台作业路径,请注意传递给
executeimmediate
的语句不能引用局部变量中的值——当执行动态SQL语句时,这些变量不在范围内。当你写作时

EXECUTE IMMEDIATE 'CREATE USER n IDENTIFIED BY p';
n
p
不引用您定义的局部变量,它们是文本标识符。这将创建一个用户“n”,其密码为单字符“p”。假设要使用表中的用户名和密码,则在组装动态SQL语句时需要使用它们。差不多

EXECUTE IMMEDIATE 
  'CREATE USER ' || :new.name ||
  ' IDENTIFIED BY ' || :new.password;

这就引出了一个问题:为什么要将信息存储在两个地方。您似乎不太可能真正想要一个表
plsql\u test\u users
,其中包含一组用户名和密码,这些用户名和密码也是Oracle用户。您或者希望Oracle处理身份验证,或者希望应用程序处理身份验证,但不希望每个应用程序都认为它正在处理身份验证(例如,当一个密码更改,而另一个密码更改时会发生什么情况)。如果您的应用程序要处理身份验证,则永远不会存储密码(或加密密码)。您将使用salt存储密码的散列(在原始列中)。然后,当用户在登录时提供密码时,您将计算并验证哈希值,并比较哈希值。

不,您无法正确执行此操作

不能在触发器内提交(通常,我将在下面讨论异常)。DDL-like
CREATE USER
发出两个隐式提交(一个在语句之前,一个在语句之后),因此不能将DDL放入触发器中

如果将触发器声明为使用自治事务,则会发生关于在触发器内提交的规则的异常。但这并不能正确地解决问题,原因有几个。首先,正如名字所说,自治事务是自治的,因此即使触发语句回滚,它也将被提交。这意味着,如果
INSERT
语句成功地插入了一行,但该更改被回滚,则自治事务将保持提交状态,这样您将在
plsql\u test\u users
表中创建一个用户,但没有任何行。出于写一致性的原因,Oracle还可能在内部回滚并重新执行一条语句,该语句将导致自治事务执行两次,第二次将失败,因为用户已经存在。自治事务实际上只应用于您希望记录信息的情况,无论基础更改是否成功(即记录尝试的登录或密码更改,以便即使不成功的登录或密码更改没有改变数据的状态,您也可以检测攻击)

您可以使用触发器调用dbms_job.submit来提交后台作业,该作业将在语句提交(如果确实提交)后不久运行,该语句将实际创建用户。这将在添加到表中的行和创建的用户之间产生一个小的延迟,但它至少在事务上是正确的(延迟可能是错误的)