. . . WHEN '00190' <> EMPLOYEE_ID (ERROR) . . . |
前述の例では、条件が、後ろにアクションまたはエラーが続くEMPLOYEE_ID列を参照しているのか、引数としてERRORを持つEMPLOYEE_IDファンクションに対するファンクション・コールを参照しているのか確認するのは困難です。トリガー定義内のファンクションをサポートするために、SQLでは、これはファンクション・コールであると想定されます。
このようなあいまいさを回避するために、WHEN句では条件を丸カッコで囲みます。
次に例を示します。
SQL> CREATE TRIGGER AFTER_T AFTER INSERT ON T cont> (INSERT INTO S VALUES (T.ID, T.SEQ)) FOR EACH ROW; SQL> ALTER TABLE S ADD COLUMN P REAL; %RDB-W-META_WARN, metadata successfully updated with the reported warning - RDMS-W-TRIG_LANGSEMEXI, table used by trigger with language dependency - trigger invalid on COMMIT SQL> COMMIT; . . . SQL> INSERT INTO T VALUES (0,0); %RDB-E-TRIG_REQ_ERROR, error encountered by a request using triggers - RDMS-E-TRG_INVALID, trigger can not be invoked - it is marked invalid -RDMS-E-TRIG_ERROR, trigger AFTER_T forced an error |
トリガーからコールできるのは、SELECT、プロシージャ文(CASE、WHILE、REPEATおよびFORカウント・ループなど)、副選択を使用するSQLプロシージャ、または外部ルーチンをコールするSQLプロシージャのみです。
これらの制限に準拠する以前のリリースで作成されたSQLプロシージャは、依然としてCREATE TRIGGERプロセスによって拒否される場合があります。この診断は、次の例のようになります。このようになるのは、このルーチンが作成されたときに正しい実行状態が記録されなかったためです。これを修正するには、DROPコマンドおよびCREATEコマンドを使用して新規バージョンを作成します。
この問題を修正するもう1つの方法は、次の例に示すように、SET FLAGS VALIDATE_ROUTINEオプションを使用します。検証が実行された後、COMMITコマンドによって状態がRDB$ROUTINESシステム表に格納され、後で使用できるようになります。
SQL> set transaction read write; SQL> SQL> -- attempt to use SQL procedure fails SQL> create trigger T_A cont> after insert on M_TABLE cont> (call SEND_MAIL ('MANAGER', M_TABLE.last_name)) cont> for each row; %RDB-E-NO_META_UPDATE, metadata update failed -RDB-E-RTN_FAIL, routine "SEND_MAIL" failed to compile or execute successfully -RDMS-E-NOTRIGRTN, this stored routine may not be called from a trigger SQL> SQL> set flags 'VALIDATE_ROUTINE'; SQL> -- use NOEXECUTE so the routine is just compiled, not executed SQL> set noexecute; SQL> -- validate the routine to set the correct routine state SQL> call SEND_MAIL ('MANAGER', ''); SQL> set execute; SQL> SQL> -- now the routine can be successfully used with the trigger definition SQL> create trigger T_A cont> after insert on M_TABLE cont> (call SEND_MAIL ('MANAGER', M_TABLE.last_name)) cont> for each row; SQL> SQL> commit; |
SQL> create table AUDIT (su char(31), ct timestamp, a integer); SQL> create table DATA_TABLE (a integer, b integer); SQL> SQL> create trigger T_AUDIT cont> after insert on DATA_TABLE cont> (trace 'before audit...'; cont> insert into AUDIT (su, ct, a) cont> values (session_user, current_timestamp, DATA_TABLE.a); cont> trace 'after audit...') cont> for each row; |
コンマ(,)は引数のセパレータであるため、TRACE文ではセミコロンを使用する必要があります。SQLでは、セミコロンがない場合、文の終わりと次の文の始まりを区別できません。
これらの制限は、将来のリリースのOracle Rdbで緩和される予定です。
例1: カスケード削除トリガーの定義次のSQLプロシージャは、EMPLOYEES表の行を削除する前に複数の表の行を削除する、サンプルの人事データベースからのトリガーを示しています。関連する各従業員行(従業員行の主キーを参照する外部キーがある表の行)が削除されます。削除される従業員ID番号(00164)は、マネージャでもある従業員に属しています。このため、DEPARTMENTS表のMANAGER_ID列は、トリガーによって指定されているとおり、NULLに設定されます。
SQL> SET TRANSACTION READ WRITE; SQL> -- SQL> -- Display the EMPLOYEE_ID_CASCADE_DELETE trigger SQL> -- in the sample database: SQL> -- SQL> SHOW TRIGGER EMPLOYEE_ID_CASCADE_DELETE EMPLOYEE_ID_CASCADE_DELETE Source: EMPLOYEE_ID_CASCADE_DELETE BEFORE DELETE ON EMPLOYEES (DELETE FROM DEGREES D WHERE D.EMPLOYEE_ID = EMPLOYEES.EMPLOYEE_ID) FOR EACH ROW (DELETE FROM JOB_HISTORY JH WHERE JH.EMPLOYEE_ID = EMPLOYEES.EMPLOYEE_ID) FOR EACH ROW (DELETE FROM SALARY_HISTORY SH WHERE SH.EMPLOYEE_ID = EMPLOYEES.EMPLOYEE_ID) FOR EACH ROW ! Also, if an employee is terminated and that employee ! is the manager of a department, set the manager_id ! null for that department. (UPDATE DEPARTMENTS D SET D.MANAGER_ID = NULL WHERE D.MANAGER_ID = EMPLOYEES.EMPLOYEE_ID) FOR EACH ROW SQL> -- SQL> -- The EMPLOYEES table has a value of '00164' SQL> -- in the EMPLOYEE_ID column: SQL> -- SQL> SELECT * FROM EMPLOYEES E WHERE E.EMPLOYEE_ID = '00164'; EMPLOYEE_ID LAST_NAME FIRST_NAME MIDDLE_INITIAL ADDRESS_DATA_1 ADDRESS_DATA_2 CITY STATE POSTAL_CODE SEX BIRTHDAY STATUS_CODE 00164 Toliver Alvin A 146 Parnell Place Chocorua NH 03817 M 28-Mar-1947 1 1 row selected SQL> -- SQL> -- SQL> -- The DEGREES table has two values of '00164' SQL> -- in the EMPLOYEE_ID column: SQL> -- SQL> SELECT * FROM DEGREES D WHERE D.EMPLOYEE_ID = '00164'; EMPLOYEE_ID COLLEGE_CODE YEAR_GIVEN DEGREE DEGREE_FIELD 00164 PRDU 1973 MA Applied Math 00164 PRDU 1982 PhD Statistics 2 rows selected SQL> -- SQL> -- SQL> -- The JOB_HISTORY table has the value of '00164' in SQL> -- several rows in the EMPLOYEE_ID column: SQL> -- SQL> SELECT * FROM JOB_HISTORY JH WHERE JH.EMPLOYEE_ID = '00164'; EMPLOYEE_ID JOB_CODE JOB_START JOB_END DEPARTMENT_CODE SUPERVISOR_ID 00164 DMGR 21-Sep-1981 NULL MBMN 00228 00164 SPGM 5-Jul-1980 20-Sep-1981 MCBM 00164 2 rows selected SQL> -- SQL> -- SQL> -- The SALARY_HISTORY table has a value of '00164' SQL> -- in several rows in the EMPLOYEE_ID column: SQL> -- SQL> SELECT * FROM SALARY_HISTORY SH WHERE SH.EMPLOYEE_ID = '00164'; EMPLOYEE_ID SALARY_AMOUNT SALARY_START SALARY_END 00164 $26,291.00 5-Jul-1980 2-Mar-1981 00164 $51,712.00 14-Jan-1983 NULL 00164 $26,291.00 2-Mar-1981 21-Sep-1981 00164 $50,000.00 21-Sep-1981 14-Jan-1983 4 rows selected SQL> -- SQL> -- SQL> -- The DEPARTMENTS table has a value of '00164' SQL> -- in the MANAGER_ID column: SQL> -- SQL> SELECT * FROM DEPARTMENTS D WHERE D.MANAGER_ID = '00164'; DEPARTMENT_CODE DEPARTMENT_NAME MANAGER_ID BUDGET_PROJECTED BUDGET_ACTUAL MBMN Board Manufacturing North 00164 NULL NULL 1 row selected SQL> -- SQL> -- SQL> -- Test the trigger by deleting the row with a value of '00164' SQL> -- in the EMPLOYEE_ID column from the EMPLOYEES table: SQL> -- SQL> DELETE FROM EMPLOYEES E WHERE E.EMPLOYEE_ID = '00164'; 1 row deleted SQL> -- SQL> -- The row with a value of '00164' in the EMPLOYEE_ID column SQL> -- was deleted from the EMPLOYEES table: SQL> -- SQL> SELECT * FROM EMPLOYEES E WHERE E.EMPLOYEE_ID = '00164'; 0 rows selected SQL> -- SQL> -- The rows with a value of '00164' in the EMPLOYEE_ID column SQL> -- were deleted from the DEGREES table: SQL> -- SQL> SELECT * FROM DEGREES D WHERE D.EMPLOYEE_ID = '00164'; 0 rows selected SQL> -- SQL> -- The rows with a value of '00164' in the EMPLOYEE_ID SQL> -- column were deleted from the JOB_HISTORY table: SQL> -- SQL> SELECT * FROM JOB_HISTORY JH WHERE JH.EMPLOYEE_ID = '00164'; 0 rows selected SQL> -- SQL> -- The rows with a value of '00164' in the EMPLOYEE_ID SQL> -- column were deleted from the SALARY_HISTORY table: SQL> -- SQL> SELECT * FROM SALARY_HISTORY SH WHERE SH.EMPLOYEE_ID = '00164'; 0 rows selected SQL> -- SQL> -- The value of '00164' in the MANAGER_ID column was set to null SQL> -- in the DEPARTMENTS table: SQL> -- SQL> SELECT * FROM DEPARTMENTS D WHERE D.DEPARTMENT_CODE = 'MBMN'; DEPARTMENT_CODE DEPARTMENT_NAME MANAGER_ID BUDGET_PROJECTED BUDGET_ACTUAL MBMN Board Manufacturing North NULL NULL NULL 1 row selected SQL> -- SQL> ROLLBACK;
例2: 更新を実行するトリガーの定義
WORK_STATUS表のSTATUS_CODE列が更新される前に、次のSQLプロシージャのSTATUS_CODE_CASCADE_UPDATEトリガーによってEMPLOYEES表の関連列が更新されます。REFERENCING句により、UPDATE文が実行される前におけるWORK_STATUS表の値の相関名としてOLD_WORK_STATUSが指定され、UPDATE文が実行された後におけるWORK_STATUS表の値の相関名としてNEW_WORK_STATUSが指定されます。
SQL> -- Display the STATUS_CODE_CASCADE_UPDATE trigger in SQL> -- the sample database: SQL> -- SQL> SHOW TRIGGER STATUS_CODE_CASCADE_UPDATE STATUS_CODE_CASCADE_UPDATE Source: STATUS_CODE_CASCADE_UPDATE BEFORE UPDATE OF STATUS_CODE ON WORK_STATUS REFERENCING OLD AS OLD_WORK_STATUS NEW AS NEW_WORK_STATUS (UPDATE EMPLOYEES E SET E.STATUS_CODE = NEW_WORK_STATUS.STATUS_CODE WHERE E.STATUS_CODE = OLD_WORK_STATUS.STATUS_CODE) FOR EACH ROW SQL> -- SQL> -- Change the STATUS_CODE column with a value of 2 to a value of 3: SQL> -- SQL> UPDATE WORK_STATUS WS SET STATUS_CODE="3" WHERE STATUS_CODE="2"; 1 row updated SQL> -- SQL> -- The trigger changes any STATUS_CODE column in the EMPLOYEES table SQL> -- with a value of 2 to a value of 3. Therefore, no rows are SQL> -- selected for the first query that follows, but several are selected SQL> -- for the second query: SQL> -- SQL> SELECT * FROM EMPLOYEES E WHERE E.STATUS_CODE = "2"; 0 rows selected SQL> -- SQL> SELECT * FROM EMPLOYEES E WHERE E.STATUS_CODE = "3"; EMPLOYEE_ID LAST_NAME FIRST_NAME MIDDLE_INITIAL ADDRESS_DATA_1 ADDRESS_DATA_2 CITY STATE POSTAL_CODE SEX BIRTHDAY STATUS_CODE 00165 Smith Terry D 120 Tenby Dr. Chocorua NH 03817 M 15-May-1954 3 00178 Goldstone Neal NULL 194 Lyons Av, Colebrook NH 03576 M 25-Apr-1952 3 . . . 00358 Lapointe Jo Ann C 70 Tenby Dr. Chocorua NH 03817 F 24-Feb-1931 3 12 rows selected SQL> -- SQL> ROLLBACK;
例3: 売上サマリーを更新するトリガーの定義
次の例は、毎日の売上が計上された後に毎月の売上合計を更新するトリガーを定義しています。
SQL> -- SQL> -- Create the table to keep track of monthly sales: SQL> CREATE TABLE MONTHLY_SALES cont> ( SALES_AMOUNT INTEGER); SQL> -- SQL> -- Create the table to keep track of sales made today: SQL> CREATE TABLE DAILY_SALES cont> ( SALES_AMOUNT INTEGER); SQL> -- SQL> -- Assume that $250.00 of sales have been made during the current month: SQL> INSERT INTO MONTHLY_SALES cont> (SALES_AMOUNT) VALUES (250); 1 row inserted SQL> -- SQL> -- After adding a new value to the SALES_AMOUNT column in SQL> -- DAILY_SALES table, SQL updates the SALES column in SQL> -- the MONTHLY_SALES table with the amount of the new sale: SQL> CREATE TRIGGER UPDATE_SALES_TOTAL_ON_NEW_SALE cont> AFTER INSERT ON DAILY_SALES cont> (UPDATE MONTHLY_SALES M cont> SET M.SALES_AMOUNT = M.SALES_AMOUNT + DAILY_SALES.SALES_AMOUNT) cont> FOR EACH ROW; SQL> -- SQL> -- The following statement records a new $5.00 sale for today: SQL> INSERT INTO DAILY_SALES cont> (SALES_AMOUNT) VALUES (5); 1 row inserted SQL> -- SQL> -- The value for the SALES_AMOUNT column of the DAILY_SALES table SQL> -- is $5.00 and the value of the SALES_AMOUNT column of the SQL> -- MONTHLY_SALES table is $255.00: SQL> SELECT * FROM DAILY_SALES; SALES_AMOUNT 5 1 row selected SQL> -- SQL> SELECT * FROM MONTHLY_SALES; SALES_AMOUNT 255 1 row selected SQL> -- SQL> -- When a new $9.00 sale is made, the values in the two rows of the SQL> -- SALES_AMOUNT column of the DAILY_SALES table are $5.00 and $9.00 SQL> -- and the value of the SALES_AMOUNT column of the MONTHLY_SALES SQL> -- table is $264.00: SQL> INSERT INTO DAILY_SALES cont> (SALES_AMOUNT) VALUES (9); 1 row inserted SQL> -- SQL> SELECT * FROM DAILY_SALES; SALES_AMOUNT 5 9 2 rows selected SQL> -- SQL> SELECT * FROM MONTHLY_SALES; SALES_AMOUNT 264 1 row selected SQL> -- SQL> ROLLBACK; SQL> --
例4: 列値をNULLに設定するトリガーの定義
WORK_STATUS表のSTATUS_CODE列を削除する前に、このトリガーにより、EMPLOYEES表の関連するWORK_STATUS列をNULLに設定しています。
SQL> CREATE TRIGGER STATUS_CODE_ON_DELETE_SET_NULL cont> BEFORE DELETE ON WORK_STATUS cont> (UPDATE EMPLOYEES E SET E.STATUS_CODE = NULL cont> WHERE E.STATUS_CODE = WORK_STATUS.STATUS_CODE) cont> FOR EACH ROW; SQL> -- SQL> -- Delete any row in the WORK_STATUS table where the STATUS_CODE SQL> -- column has a value of 1: SQL> DELETE FROM WORK_STATUS WS WHERE WS.STATUS_CODE = "1"; 1 row deleted SQL> -- SQL> -- This trigger sets the STATUS_CODE column value to null in many SQL> -- rows in the EMPLOYEES table: SQL> SELECT * FROM EMPLOYEES E WHERE E.STATUS_CODE IS NULL; EMPLOYEE_ID LAST_NAME FIRST_NAME MIDDLE_INITIAL ADDRESS_DATA_1 ADDRESS_DATA_2 CITY STATE POSTAL_CODE SEX BIRTHDAY STATUS_CODE 00416 Ames Louie A 61 Broad st. NULL Alton NH 03809 M 13-Apr-1941 NULL 00374 Andriola Leslie Q 111 Boston Post Rd. NULL Salisbury NH 03268 M 19-Mar-1955 NULL . . . 00200 Ziemke Al F 121 Putnam Hill Rd. NULL Winnisquam NH 03289 M 27-Oct-1928 NULL 88 rows selected SQL> ROLLBACK;
例5: 2つの表内に存在する行の削除を防止するトリガーの定義
JOB_HISTORY表の行のうち、JOBS表にも存在しない行のみを削除する必要があるとします。ただし、他の表には存在しないキー番号を持つ行が1つの表内に存在する場合があるため、制約を使用してこれを実行するのは困難です。次の文では、JOB_HISTORY表内に存在する行を削除しようとするとエラーが発生するトリガーを作成しています。
SQL> CREATE TRIGGER DELETE_GUARD cont> BEFORE DELETE ON JOB_HISTORY cont> WHEN EXISTS (SELECT JOBS.JOB_CODE FROM JOBS cont> WHERE JOBS.JOB_CODE=JOB_HISTORY.JOB_CODE) cont> (ERROR) FOR EACH ROW; SQL> -- SQL> -- Now attempt a deletion that violates the trigger. SQL> -- SQL> DELETE FROM JOB_HISTORY WHERE JOB_CODE = 'DMGR'; %RDB-E-TRIG_INV_UPD, invalid update; encountered error condition defined for trigger -RDMS-E-TRIG_ERROR, trigger DELETE_GUARD forced an error -RDB-F-ON_DB, on database DISK1:[DEPT3.SQL]MF_PERSONNEL.RDB;1
例6: 監査情報を保存するトリガーの定義
SQL> -- Create new table to record changes made to SQL> -- EMPLOYEES table SQL> CREATE TABLE AUDIT_TRAIL cont> (LOG DATE VMS, cont> PERSON CHAR(31), cont> TBL_NAME CHAR(10), cont> OPER CHAR(1)); SQL> COMMIT; SQL> -- Create a trigger so that each time SQL> -- an INSERT operation is performed, SQL> -- a record is stored in the AUDIT_TRAIL table. SQL> CREATE TRIGGER EMPS_TRIGGER cont> AFTER INSERT cont> ON EMPLOYEES cont> (INSERT INTO AUDIT_TRAIL cont> VALUES (CURRENT_TIMESTAMP, cont> CURRENT_USER, 'EMPLOYEES', 'I')) cont> FOR EACH STATEMENT; SQL> -- The AUDIT_TRAIL table currently has no records. SQL> SELECT * FROM AUDIT_TRAIL; 0 rows selected SQL> -- Insert a record into EMPLOYEES SQL> INSERT INTO EMPLOYEES cont> (EMPLOYEE_ID, LAST_NAME) cont> VALUES ('00964', 'FRENCH'); 1 row inserted SQL> -- See if trigger updated the AUDIT_TRAIL table. SQL> SELECT * FROM AUDIT_TRAIL; LOG PERSON TBL_NAME OPER 17-JUN-2003 15:04:31.43 STEWART EMPLOYEES I 1 row selected
例7: トリガー・アクションとしてのTRACEの使用
SQL> set flags 'TRACE'; SQL> create table M_TABLE (a integer, b integer); SQL> SQL> create trigger T_A cont> after insert on M_TABLE cont> (trace 'in a trigger: ' || cast(M_TABLE.a as varchar(10))) cont> for each row; SQL> SQL> insert into M_TABLE (a, b) values (1, 10); ~Xt: in a trigger: 1 1 row inserted SQL>
例8: トリガー・アクションとしてのSIGNALの使用
SQL> create table M_TABLE (a integer, b integer); SQL> SQL> create trigger T_A cont> after insert on M_TABLE2 cont> when (M_TABLE2.a is not null) cont> (signal '12345' ('in a trigger: ' cont> || cast(M_TABLE2.a as varchar(10)))) cont> for each row; SQL> SQL> insert into M_TABLE2 (a, b) values (1, 10); %RDB-E-SIGNAL_SQLSTATE, routine "T_A" signaled SQLSTATE "12345" -RDB-I-TEXT, in a trigger: 1 SQL>
例9: トリガー・アクションとしてのCALLの使用
SQL> create module M_MODULE cont> language SQL cont> cont> procedure M_K (in :a int); cont> trace 'called from a trigger: ' || cast(:a as varchar(10)); cont> cont> end module; SQL> SQL> create table M_TABLE (a integer, b integer); SQL> SQL> create trigger T_A cont> after insert on M_TABLE cont> (call M_K (M_TABLE.a)) cont> for each row; SQL> SQL> insert into M_TABLE (a, b) values (1, 10); ~Xt: called from a trigger: 1 1 row inserted SQL>
特殊セキュリティ・プロファイル・エントリを作成して、データベース・ユーザーを識別します。このユーザーには、データベース・オブジェクトにアクセスするためのロールを付与します。
CREATE USER文は次の環境で使用できます。
- 対話型SQL内
- ホスト言語プログラムに埋め込まれる場合
- SQLモジュールまたはその他の複合文のプロシージャの一部として
- 動的SQLで動的に実行される文として
ACCOUNT LOCK
ACCOUNT UNLOCK
ACCOUNT LOCK句により、CREATE USER文が適用されているユーザーによるデータベースへのアクセスを無効にします。ACCOUNT UNLOCK句により、ユーザーによるデータベースへのアクセスを許可します。COMMENT IS 'string'
ユーザーに関するコメントを追加します。 SQLでは、SHOW USERS文の実行時にコメントのテキストが表示されます。 コメントは一重引用符(')で囲み、コメント内の複数の行はスラッシュ(/)で区切ります。IDENTIFIED EXTERNALLY
ユーザーがオペレーティング・システムを介して認証されるよう指定します。NOPROFILE
NOPROFILEはデフォルトの動作で、このユーザーに特殊制限が適用されないよう指定します。PROFILE
ユーザーに割り当てる新規プロファイルを識別します。指定されたプロファイル名は、既存のプロファイル名と一致する必要があります。PUBLIC
データベース内にPUBLICセキュリティ・プロファイル・エントリを明示的に作成します。username
データベースに追加するユーザー名です。これは、既存のOpenVMSユーザー名と一致する必要があります。
- ユーザーを作成するには、データベースに対するSECURITY権限が必要です。
- 特殊ユーザーPUBLICは暗黙的に存在します。ただし、CREATE USER文を使用して明示的なPUBLICエントリを作成することにより、ロールおよびプロファイルをPUBLICユーザーに関連付けることができます。これにより、データベースにアクセスする匿名ユーザーを制御できるようになります。
- SHOW USERS文を発行することにより、データベースに定義されている既存のユーザーを表示できます。
- ユーザー名は、OpenVMSネーミング規則に準拠する必要があります。つまり、大文字、数値、アンダースコアおよび$を使用し、空白または記号は使用できません。
- SECURITY CHECKING IS INTERNALである場合、ユーザーがデータベースに定義されておらず、この名前がOpenVMSユーザーとして存在する場合、GRANT文により、CREATE USERが暗黙的に実行されます。次の例では、ユーザーが作成されています。
SQL> grant ADMIN_USER to SMITH; %RDB-W-META_WARN, metadata successfully updated with the reported warning -RDMS-W-PRFCREATED, some users or roles were created SQL> show users Users in database with filename personnel SMITH
例1: 新規ユーザーの作成とそのアカウントのロック
SQL> CREATE USER munroy IDENTIFIED EXTERNALLY cont> ACCOUNT LOCK cont> COMMENT IS 'User munroy starts job on'/ cont> 'May 1, 2003. Unlock when she starts';
例2: ユーザーへのプロファイルの追加
この例では、DEFAULTトランザクションを定義する新規プロファイルを作成し、新規ユーザーの作成時にプロファイルを割り当てます。ユーザーがデータベースに次回アタッチするときに、START DEFAULT TRANSACTION文では、定義されたプロファイルが標準のデフォルトのREAD ONLYのかわりに使用されます。
SQL> create profile READ_COMMITTED cont> default transaction read write isolation level read committed wait 30; SQL> show profile READ_COMMITTED READ_COMMITTED Default transaction read write wait 30 Isolation level read committed SQL> create user JAIN identified externally profile READ_COMMITTED; SQL> show user JAIN; JAIN Identified externally Account is unlocked Profile: READ_COMMITTED No roles have been granted to this user