2

テーブル User を含む 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;

EDIT2

トリガーの外でプロシージャを呼び出す方法:

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:
4

1 に答える 1

2

1)@Bob Jarvisが示唆したように、に渡す予定のSQLステートメントを作成するときEXECUTE IMMEDIATE、そのSQLステートメントには末尾のセミコロンを含めないでください;

2)CREATE USERGRANTは 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;
于 2012-06-28T17:54:50.087 に答える