如果有可能......怎么办?我是数据库新手,请帮助我! 我在使用oracle时想要在我在表格中插入新行时创建新用户"用户"
答案 0 :(得分:0)
正如JGreenwell所说,是的,你可以做到,但这不是一个好主意。主要问题是密码不清楚,是交易副作用。
让我们看一下明确的密码解决方案:
很容易解决密码问题(不要将密码存储清除,加密或散列密码)。如果您已经安装了DMBS_CRYPTO并拥有它的权限,那么您可以创建一个过程(我假设您有一个表USERS与列:USERNAME和USERPASS):
CREATE OR REPLACE PROCEDURE MYCREATEUSER( NAME VARCHAR, PASS VARCHAR )
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE 'CREATE USER ' || NAME || ' IDENTIFIED BY "' || PASS || '"';
END;
和触发器:
CREATE OR REPLACE TRIGGER TUSERS BEFORE INSERT ON USERS FOR EACH ROW
BEGIN
MYCREATEUSER(:NEW.USERNAME, :NEW.USERPASS);
:NEW.USERPASS := DBMS_CRYPTO.HASH(:NEW.USERPASS, DBMS_CRYPTO.HASH_SH1);
END;
您的insert语句使用用户名和密码,触发器会创建用户,但在插入行之前,它会用SHA1哈希值替换密码。查询表时必须记住这一点。
一个例子:
INSERT INTO USERS VALUES('Mary', 'Mary123');
检查:
SELECT COUNT(*)
FROM USERS
WHERE USERNAME = 'Mary' AND
USERPASS = DBMS_CRYPTO.HASH('Mary123', DBMS_CRYPTO.HASH_SH1);
如果count = 1则存在用户和密码,但如果count = 0,则用户/密码不存在。
此示例仅在以下情况下有效:您已安装DBMS_CRYPTO且具有足够的权限,并且您具有CREATE TABLE权限(请记住,当过程执行语句时,它只具有明确授予的权限,来自ROLES的权限被禁用 - 因此,它如果没有RESOURCE权限,则需要CREATE TABLE显式权限。
但正如我所提到的,这不是一个好主意,因为你可能会受到交易副作用的影响。让我们看看主要问题:
为了维护ACID原则(原子性,一致性,隔离性和持久性),Oracle需要确保将一个语句视为原子操作。如果我执行INSERT INTO USERS SELECT * FROM OTHER_USER_TABLES,则必须将此语句视为原子单元。发送语句时原子单元开始,当oracle通知你错误/ ok代码时结束。
但触发器在语句内部执行(在其时间范围内)。触发器控制insert语句(如果失败则所有语句都失败,如果说没问题,语句就可以了)。请注意,语句在触发器完成后结束。这意味着在语句结束之前无法提交或回滚当前事务(因为在这种情况下,不能确保原子性)。因此,触发器不能COMMIT / ROLLBACK当前事务(它不能提交,它不能调用程序来提交它,没有人可以在语句结束之前完成)。 CREATE TABLE是一个自动提交语句(如果强制提交),因此无法在触发器范围内创建表。
但我们说"你可以"我们有一个有效的例子。怎么样? 答案是PRAGMA AUTONOMOUS_TRANSACTION。 该pragma强制oracle在新的不同事务中执行受影响的PL / SQL块。因此,在我们的示例中,oracle在新事务中执行MYCREATEUSER过程。
Oracle没有嵌套的事务模型,因此内部AUTONOMOUS_TRANSACTION不依赖于外部触发器的事务。它们都是扁平交易。这意味着如果过程结束(创建用户)并且插入最终失败(由于任何原因),则该行不在表中,但新用户存在。
让我们看一个例子:
INSERT INTO USERS VALUES ('Anne', 'An232131');
INSERT INTO USERS VALUES ('Mike', "ABC123');
ROLLBACK;
此示例插入两行(它创建两个用户)并回滚事务。因此,最后插入被取消,行(Anne和Mike)不在用户表中。但是Anne和Mike Oracle的用户存在(回滚)不会影响用户创建,因为它们是由最终提交的不同事务(自治事务)创建的。
如果没有嵌套的事务模型,这个问题就不容易解决(在嵌套事务模型中,内部事务最终只在外部事务发生时提交)。