. . . SQL> CREATE TABLE TAB1 (a1 int CONSTRAINT TAB1NOTNULL NOT NULL , cont> a2 char(10), cont> a3 char(10) ); SQL> CREATE OUTLINE TAB1NOTNULL cont> id '8755644BCB040948E28A76B6D77CC2D3' cont> MODE 0 cont> AS ( cont> QUERY ( cont> SUBQUERY ( cont> TAB1 0 ACCESS PATH SEQUENTIAL cont> ) cont> ) cont> ) cont> COMPLIANCE OPTIONAL ; SQL> CREATE TRIGGER TAB1TRIG BEFORE INSERT ON TAB1 cont> (UPDATE TAB1 SET a3= 'bbbb' WHERE a2 = 'aaaa' ) FOR EACH ROW; SQL> CREATE OUTLINE TAB1TRIG cont> id '990F90B45658D27D64233D88D16AD273' cont> MODE 0 cont> AS ( cont> QUERY ( cont> SUBQUERY ( cont> TAB1 0 ACCESS PATH SEQUENTIAL cont> ) cont> ) cont> ) cont> COMPLIANCE OPTIONAL ; . . . $ DEFINE RDMS$DEBUG_FLAGS "SnsI" . . . SQL> INSERT INTO tab1 (a1) VALUE (11); ~S: Trigger name TAB1TRIG ~S: Outline TAB1TRIG used ~S: Outline TAB1NOTNULL used Conjunct Get Retrieval sequentially of relation TAB1 . . . 1 row inserted SQL> commit; ~S: Constraint TAB1NOTNULL evaluated Conjunct Get Retrieval sequentially of relation TAB1 . . . |
SQL> DECLARE :ln CHAR(40); SQL> SQL> BEGIN cont> TRACE 'Jobs Held: ', cont> (SELECT COUNT(*) cont> FROM job_history cont> WHERE employee_id = '00201'); cont> SELECT last_name cont> INTO :ln cont> FROM employees cont> WHERE employee_id = '00201'; cont> END; -- Oracle Rdb Generated Outline : 28-MAY-1997 16:48 create outline QO_A17FA4B41EF1A68B_00000000 id 'A17FA4B41EF1A68B966C1A0B083BFDD4' mode 0 as ( query ( -- Select subquery ( EMPLOYEES 0 access path index EMPLOYEES_HASH ) ) ) compliance optional ; SQL> |
TRACEが有効な場合に問合せアウトラインが生成されると、問合せはTRACE文の副問合せ用、およびシングルトンSELECT文用の2つが表示されます。
SQL> DECLARE :ln CHAR(40); SQL> SQL> BEGIN cont> TRACE 'Jobs Held: ', cont> (SELECT COUNT(*) cont> FROM job_history cont> WHERE employee_id = '00201'); cont> SELECT last_name cont> INTO :ln cont> FROM employees cont> WHERE employee_id = '00201'; cont> END; -- Oracle Rdb Generated Outline : 28-MAY-1997 16:48 create outline QO_A17FA4B41EF1A68B_00000000 id 'A17FA4B41EF1A68B966C1A0B083BFDD4' mode 0 as ( query ( -- Trace subquery ( JOB_HISTORY 0 access path index JOB_HISTORY_HASH ) ) query ( -- Select subquery ( EMPLOYEES 0 access path index EMPLOYEES_HASH ) ) ) compliance optional ; ~Xt: Jobs Held: 4 SQL> |
この2番目の問合せアウトラインはTRACE文が無効のまま実行時に使用されると、次の例に示すように、問合せに適用できません。
SQL> DECLARE :ln CHAR(40); SQL> SQL> BEGIN cont> TRACE 'Jobs Held: ', cont> (SELECT COUNT(*) cont> FROM job_history cont> WHERE employee_id = '00201'); cont> SELECT last_name cont> INTO :ln cont> FROM employees cont> WHERE employee_id = '00201'; cont> END; ~S: Outline QO_A17FA4B41EF1A68B_00000000 used ~S: Outline/query mismatch; assuming JOB_HISTORY 0 renamed to EMPLOYEES 0 ~S: Full compliance with the outline was not possible Get Retrieval by index of relation EMPLOYEES Index name EMPLOYEES_HASH [1:1] Direct lookup |
アウトラインは準拠が任意で作成されているため、この問合せアウトラインは破棄され、新しい計画が計算されます。準拠が必須の場合、問合せは失敗します。
いずれかのTRACE文に副問合せが含まれている場合、TRACEが有効および有効でない状態で問合せを実行するため、2つの問合せアウトラインが必要であれば、これを別々のモードで使用することをお薦めします。つまり、TRACEが有効な場合、TRACEが有効な状態の問合せアウトラインに一致するようにRDMS$BIND_OUTLINE_MODEを定義します。
$ DEFINE RDMS$DEBUG_FLAGS "Xt" $ DEFINE RDMS$DEBUG_FLAGS_OUTPUT TRACE.DAT $ DEFINE RDMS$BIND_OUTLINE_MODE 10 |
またはSET FLAGS文を使用します。この文を使用すると、対話型セッション内で、または動的SQLを介してTRACEフラグを有効化し、MODEを確立できます。このスキームを使用すると、TRACEが有効でも無効でも問合せを実行できます。
SQL> SET FLAGS 'MODE(10),OUTLINE'; SQL> SHOW FLAGS Alias RDB$DBHANDLE: Flags currently set for Oracle Rdb: PREFIX,OUTLINE,MODE(10) SQL> SELECT COUNT(*) FROM employees; -- Rdb Generated Outline : 30-MAY-1997 16:35 create outline QO_B3F54F772CC05435_0000000A id 'B3F54F772CC054350B2B454D95537995' mode 10 as ( query ( -- For loop subquery ( subquery ( EMPLOYEES 0 access path index EMP_EMPLOYEE_ID ) ) ) ) compliance optional ; 100 1 row selected |
次のオプションを使用できます。
前述の例では、問合せアウトラインの生成時にモードが10に設定されていました。生成されたアウトラインがデータベースに追加されると、そのアウトラインはSET FLAGS文により、または論理名RDMS$BIND_OUTLINE_MODEを使用して、モードが10に設定されている場合にのみ使用されます。
SQL> BEGIN cont> -- Find the employee and cont> -- complete their current job, before being promoted cont> FOR :cur AS EACH ROW OF CURSOR a cont> FOR SELECT last_name cont> FROM EMPLOYEES cont> WHERE employee_id = :emp_id cont> DO cont> BEGIN cont> -- Display some details cont> TRACE 'Employee: ', :cur.last_name; cont> cont> FOR :cur2 AS EACH ROW OF CURSOR b cont> FOR SELECT cast(job_start AS DATE ANSI) AS js, cont> cast(job_end AS DATE ANSI) AS je cont> FROM JOB_HISTORY cont> WHERE employee_id = :emp_id cont> ORDER BY job_start cont> DO cont> TRACE ' Job Duration: ', cont> (COALESCE (:cur2.je, current_date) - :cur2.js) YEAR TO MONTH; cont> END FOR; cont> cont> -- Now complete the current job cont> UPDATE JOB_HISTORY cont> SET job_end = CAST(current_date AS DATE VMS) cont> WHERE employee_id = :emp_id; cont> cont> END; cont> END FOR; cont> END; -- Oracle Rdb Generated Outline : 29-MAY-1997 22:52 create outline QO_39BBA6C4E902AB2B_00000000 id '39BBA6C4E902AB2B6A252A71A1CFFB71' mode 0 as ( query ( -- For loop subquery ( EMPLOYEES 0 access path index EMPLOYEES_HASH ) ) query ( -- For loop subquery ( JOB_HISTORY 0 access path index JOB_HISTORY_HASH ) ) query ( -- Update subquery ( JOB_HISTORY 0 access path index JOB_HISTORY_HASH ) ) ) compliance optional ; |
問合せアウトライン内の問合せの順序は、複合文の複雑な実行プロファイルを表すフラット化ツリー構造を表しています。このツリー構造を抽出すると、最適化フェーズのボトムアップ表現に関連する順序が生成されます。
その結果、ネストされた文のあるプロシージャに対して生成された問合せアウトラインでは順序が逆になり、問合せアウトラインでは最後に表示されるEMPLOYEES表が最初に表示される場合があります。
-- Oracle Rdb Generated Outline : 29-MAY-1997 22:52 create outline QO_39BBA6C4E902AB2B_00000000 id '39BBA6C4E902AB2B6A252A71A1CFFB71' mode 0 as ( query ( -- For loop subquery ( JOB_HISTORY 0 access path index JOB_HISTORY_HASH ) ) query ( -- Update subquery ( JOB_HISTORY 0 access path index JOB_HISTORY_HASH ) ) query ( -- For loop subquery ( EMPLOYEES 0 access path index EMPLOYEES_HASH ) ) ) compliance optional ; |
SQL> create outline CURRENT_JOB on view CURRENT_JOB; SQL> show outline CURRENT_JOB CURRENT_JOB Source: -- Rdb Generated Outline : 16-MAY-2001 15:11 create outline CURRENT_JOB -- On view CURRENT_JOB id '9C6D98DAAF09A3E1796F7D345399028B' mode 0 as ( query ( -- View subquery ( JOB_HISTORY 0 access path sequential join by cross to EMPLOYEES 1 access path index EMPLOYEES_HASH ) ) ) compliance optional ; |
この代替定義では、JOB_HISTORYに対して索引が指定されています。
SQL> create outline CURRENT_JOB cont> on view CURRENT_JOB cont> mode 0 cont> as ( cont> query ( cont> -- View cont> subquery ( cont> JOB_HISTORY 0 access path index JH_EMPLOYEE_ID cont> join by cross to cont> EMPLOYEES 1 access path index EMPLOYEES_HASH cont> ) cont> ) cont> ) cont> compliance optional cont> comment is 'qo for view CURRENT_JOB'; |
次の問合せでは、この問合せアウトラインを適用した結果を示します。表RETIRED_EMPLOYEESには、その名前が示すとおり、退職したすべての従業員が含まれています。したがって、これらの従業員には仕事が割り当てられないため、問合せではゼロ行が返されます。
SQL> -- should return no rows, since the employee retired and SQL> -- there is no current job SQL> set flags 'strategy'; SQL> select EMPLOYEE_ID cont> from CURRENT_JOB cj cont> inner join RETIRED_EMPLOYEES re cont> using (EMPLOYEE_ID) cont> where EMPLOYEE_ID = '00164'; ~S: Outline "CURRENT_JOB" used Cross block of 2 entries Cross block entry 1 Index only retrieval of relation RETIRED_EMPLOYEES Index name RE_EMPLOYEE_ID [1:1] Cross block entry 2 Cross block of 2 entries Cross block entry 1 Conjunct Leaf#01 FFirst JOB_HISTORY Card=274 BgrNdx1 JH_EMPLOYEE_ID [1:1] Bool Fan=17 Cross block entry 2 Conjunct Index only retrieval of relation EMPLOYEES Index name EMPLOYEES_HASH [1:1] Direct lookup 0 rows selected SQL> |
問合せアウトラインCURRENT_JOBが使用中とされていることに注意してください。
例1: AVAILABLE_EMPLOYEESというアウトラインの作成
SQL> CREATE OUTLINE available_employees cont> ID '09ADFE9073AB383CAABC4567BDEF3832' MODE 0 cont> AS ( cont> QUERY ( cont> -- cont> -- Cross the employees table with departments table first. cont> -- cont> employees 0 ACCESS PATH SEQUENTIAL JOIN BY MATCH TO cont> departments 3 ACCESS PATH INDEX dept_index JOIN BY MATCH TO cont> SUBQUERY ( cont> job_fitness 2 ACCESS PATH INDEX job_fit_emp, job_fit_dept cont> JOIN BY CROSS TO cont> SKILLS 4 ACCESS PATH ANY cont> ) JOIN BY MATCH TO cont> SUBQUERY ( cont> major_proj 1 ACCESS PATH ANY JOIN BY CROSS TO cont> education 6 ACCESS PATH ANY cont> ) JOIN BY CROSS TO cont> research_projects 5 ACCESS PATH ANY UNION WITH cont> -- cont> -- Always do the union with employees table last cont> -- cont> employees 7 ACCESS PATH ANY cont> ) cont> ) cont> COMPLIANCE OPTIONAL cont> COMMENT IS 'Available employees';
例2: FROM句を使用したアウトラインの作成
SQL> CREATE OUTLINE degrees_for_emps_over_65 cont> FROM cont> (SELECT e.last_name, e.first_name, e.employee_id, cont> d.degree, d.year_given cont> FROM employees e, degrees d cont> WHERE e.birthday < '31-Dec-1930' cont> AND e.employee_id = d.employee_id cont> ORDER BY e.last_name) cont> USING cont> (QUERY cont> (SUBQUERY cont> (degrees 1 ACCESS PATH SEQUENTIAL cont> JOIN BY CROSS TO cont> employees 0 ACCESS PATH ANY cont> ) cont> ) cont> ) cont> COMPLIANCE OPTIONAL cont> COMMENT IS 'Outline to find employees over age 65 with college degrees'; SQL> -- SQL> SHOW OUTLINE degrees_for_emps_over_65 DEGREES_FOR_EMPS_OVER_65 Comment: Outline to find employees over age 65 with college degrees Source: -- Rdb Generated Outline : 13-NOV-1995 15:28 create outline DEGREES_FOR_EMPS_OVER_65 id 'B6923A6572B28E734D6F9E8E01598CD8' mode 0 as ( query ( subquery ( DEGREES 1 access path sequential join by cross to EMPLOYEES 0 access path index EMPLOYEES_HASH ) ) ) compliance optional ;
例3: ON FUNCTION句を使用したアウトラインの作成
SQL> CREATE OUTLINE out1 cont> ON FUNCTION NAME function1; SQL> COMMIT; SQL> SHOW OUTLINE out1 OUT1 Source: -- Rdb Generated Outline : 2-FEB-1996 15:46 create outline OUT1 id '264A6DDADCB483AE5B2CDF629C9C8C0F' mode 0 as ( query ( subquery ( EMPLOYEES 0 access path index EMPLOYEES_HASH ) ) ) compliance optional ;
例4: 宣言されたローカル一時表にアクセスするプロシージャに対するアウトラインの作成(ストアド・プロシージャおよび一時表定義についてはCREATE MODULE文を参照)
SQL> CREATE OUTLINE outline1 cont> ON PROCEDURE NAME paycheck_ins_decl cont> MODE 0 cont> AS ( cont> QUERY ( cont> module.paycheck_decl_tab MODULE paycheck_decl_mod cont> 0 cont> ACCESS PATH SEQUENTIAL cont> ) cont> ) cont> COMPLIANCE OPTIONAL; SQL> SHOW OUTLINE outline1 OUTLINE1 Source: create outline OUTLINE1 mode 0 as ( query ( PAYCHECK_DECL_TAB MODULE PAYCHECK_DECL_MOD 0 access path sequential ) ) compliance optional ;
例5: 問合せアウトラインからの新規出力
SQL> BEGIN cont> DECLARE :x INTEGER; cont> -- Assignment cont> SET :x = (SELECT COUNT(*) FROM TOUT_1); cont> -- Delete statement cont> DELETE FROM TOUT_1; cont> -- Update statement cont> UPDATE TOUT_1 cont> SET a = (SELECT AVG(a) FROM TOUT_2) cont> WHERE a IS NULL; cont> -- Singleton Select cont> SELECT a INTO :x cont> FROM TOUT_1 cont> WHERE a = 1; cont> -- Trace (nothing if TRACE is disabled) cont> TRACE 'The first value: ', (SELECT a FROM TOUT_1 LIMIT TO 1 ROW); cont> END;
Oracle Rdbにより生成される問合せアウトラインは、アウトライン内のQUERYキーワードの後にコメントとともに表示されます。
-- Rdb Generated Outline : 29-MAY-1997 23:17 create outline QO_C11395E6020C6FFA_00000000 id 'C11395E6020C6FFA5A183A6CCE7C1F33' mode 0 as ( query ( -- Set subquery ( TOUT_1 0 access path sequential ) ) query ( -- Delete subquery ( TOUT_1 0 access path sequential ) ) query ( -- Update subquery ( subquery ( TOUT_2 1 access path sequential ) join by cross to subquery ( TOUT_1 0 access path sequential ) ) ) query ( -- Select subquery ( TOUT_1 0 access path sequential ) ) query ( -- Trace subquery ( TOUT_1 0 access path sequential ) ) ) compliance optional ;
Oracle Rdbデータベースにスキーマ・オブジェクトとして外部プロシージャを作成します。CREATE PROCEDURE文の詳細は、「CREATE ROUTINE文」を参照してください。外部プロシージャ定義の作成の詳細は、「CREATE ROUTINE文」を参照してください。
トランザクションやリソース使用率を制御する特殊な属性により、データベース内のユーザー定義を拡張するプロファイルを作成します。
CREATE PROFILE文は次の環境で使用できます。
- 対話型SQL内
- ホスト言語プログラムに埋め込まれる場合
- SQLモジュールまたはその他の複合文のプロシージャの一部として
- 動的SQLで動的に実行される文として
COMMENT IS 'string'
このオプションの句は、複数行のコメントをプロファイル・オブジェクトに追加する場合に使用できます。コメントはSHOW PROFILES文によって表示されます。コメントは一重引用符(')で囲み、コメント内の複数の行はスラッシュ(/)で区切ります。DEFAULT TRANSACTION
DEFAULT TRANSACTIONは、ユーザーにデフォルトのトランザクションを指定します。デフォルトでは、明示的に開始されるものがなければ、READ WRITEトランザクションが開始されます。この定義を利用するには、DECLARE TRANSACTION文またはSTART DEFAULT TRANSACTION文を使用します。この句は、DECLARE文またはSET TRANSACTION文でオーバーライドできます。
注意
Oracle Rdbでは、デフォルトのトランザクションでRESERVING句やEVALUATING句は使用できません。
LIMIT CPU TIME
NO LIMIT CPU TIME
LIMIT CPU TIMEは、問合せコンパイラで使用できる最大CPUタイムを設定します。デフォルトはNO LIMIT CPU TIMEです。
注意
この句の実行時のサポートは、Oracle Rdbリリース7.1では完全ではありません。
LIMIT ROWS
NO LIMIT ROWS
LIMIT ROWSは、ユーザーが開始した問合せから返される最大行数を設定します。デフォルトはNO LIMIT ROWSです。
注意
この句の実行時のサポートは、Oracle Rdbリリース7.1では完全ではありません。
LIMIT TIME
NO LIMIT TIME
LIMIT TIMEは、問合せコンパイラで使用できる最大経過時間を設定します。デフォルトはNO LIMIT TIMEです。
注意
この句の実行時のサポートは、Oracle Rdbリリース7.1では完全ではありません。
TRANSACTION MODES
NO TRANSACTION MODES
TRANSACTION MODESは、そのユーザーが使用可能なトランザクションのリストを提供します。トランザクション・モードの詳細は、CREATE DATABASE文およびALTER DATABASE文のSET TRANSACTION MODES句を参照してください。指定されるトランザクション・モードには、CREATE文、IMPORT文またはALTER DATABASE文により、すべてのデータベース・ユーザーに対して無効化されているモードが含まれる場合もあります。ただし、プロファイルとデータベース設定の両方で許可されているサブセットのみ使用されます。たとえば、データベースで(READ ONLY、SHARED READ、PROTECTED READ)と指定され、プロファイルで(READ ONLY、SHARED)と指定されている場合、そのサブセット(READ ONLY、SHARED READ)のセッションのみが許可されます。
次の例では、このプロファイルが割り当てられた任意のユーザーが使用できるトランザクション・モードを指定します。
SQL> CREATE PROFILE DECISION_SUPPORT cont> COMMENT IS 'limit transactions used by report writers' cont> TRANSACTION MODES (NO READ WRITE, READ ONLY);
権限や他のロールを付与できるロールを作成します。ロールは、ユーザーまたは別のロールに対して付与できます。たとえば、ある部門のメンバーに対してロールを作成できます。ユーザーがその部門から異動した場合、そのユーザーの部門ロールを取り消し、部門データへのユーザーのアクセスを排他にすることが可能です。
CREATE ROLE文は次の環境で使用できます。
- 対話型SQL内
- ホスト言語プログラムに埋め込まれる場合
- SQLモジュールまたはその他の複合文のプロシージャの一部として
- 動的SQLで動的に実行される文として
COMMENT IS 'string'
ロールに関するコメントを追加します。SQLでは、SHOW ROLES文の実行時にコメントのテキストが表示されます。コメントは一重引用符(')で囲み、コメント内の複数の行はスラッシュ(/)で区切ります。IDENTIFIED EXTERNALLY
IDENTIFIED EXERNALLY句は、SQLが権利識別子など、オペレーティング・システムのファシリティで定義されたロールを継承することを示します。セッションを開始すると、外部で定義されたすべてのロールが現行ユーザーのプロファイルの一部として構成されます。NOT IDENTIFIED
このロールがデータベースでのみ使用されることを示します。この句を使用する前に、データベースにSECURITY CHECKING IS INTERNALを設定する必要があります。role-name
ロールに割り当てるユーザー指定の名前です。特殊ロールであるBATCH、DIALUP、INTERACTIVE、LOCAL、NETWORKおよびREMOTEは、予約名のためrole-nameとしては指定できません。
- ロールを作成するには、データベースに対するSECURITY権限が必要です。
- 特殊ロールであるBATCH、DIALUP、INTERACTIVE、LOCAL、NETWORKおよびREMOTEは、ユーザー・プロセスの作成時にOpenVMSオペレーティング・システムによって付与されます。したがって、これらのロールは予約名であり、CREATE ROLE文でrole-nameとしては使用できません。
- データベースのロールが事前に定義されておらず、既存のOpenVMS権利識別子の名前に一致する場合は、SECURITY CHECKING IS INTERNALとして設定されているデータベース内でGRANT文によって暗黙的に作成されます。
- role-nameには任意の有効なSQL名を指定できます。IDENTIFIED EXTERNALLYが使用されている場合、名前はOpenVMSのネーミング規則に準拠する必要があります。つまり、大文字、数字、アンダースコアおよび$を使用し、記号として空白は使用できません。
- SECURITY CHECKING IS EXTERNALが設定されている場合は、ロールを参照用に作成できます。
- SECURITY CHECKING IS INTERNALである場合、ロールがデータベースに定義されておらず、この名前がOpenVMS権利識別子として存在する場合、GRANT文により、CREATE ROLEが暗黙的に実行されます。次の例では、ユーザーとロールの両方が作成されます。
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 SQL> show roles Roles in database with filename personnel ADMIN_USER
データベース管理者に対して、なんらかの暗黙的なアクションが実行されたか、そうでなければGRANT文は成功したことを示す警告メッセージが表示されます。
注意
この例では、SECURITY CHECKING IS INTERNALと指定されているデータベースを参照しています。
- SHOW ROLES文を発行すると、データベースに対して定義されている既存のロールを表示できます。
例1: ロールの作成
SQL> ALTER DATABASE FILENAME 'mf_personnel.rdb' cont> SECURITY CHECKING IS INTERNAL; SQL> ATTACH 'FILENAME mf_personnel.rdb'; SQL> CREATE ROLE WRITER; SQL> SHOW ROLES; Roles in database with filename mf_personnel.rdb WRITER
例2: ロールの作成と作成したロールに対する権限の付与
SQL> ALTER DATABASE FILENAME mf_personnel.rdb cont> SECURITY CHECKING IS INTERNAL; SQL> -- Create a role for employees in the payroll department SQL> ATTACH 'FILENAME MF_PERSONNEL.RDB'; SQL> CREATE ROLE PAYROLL cont> COMMENT IS 'This role allows access to various tables' cont> / 'and procedures for use by the PAYROLL dept.'; SQL> -- Create another role for a subset of employees. SQL> CREATE ROLE ANNUAL_LEAVE cont> COMMENT IS 'This role is granted to PAYROLL personnel' cont> / 'who adjust the annual leave data'; SQL> -- Grant EXECUTE privilege on module and ALL privilege on table SQL> -- SALARY_HISTORY to all employees to whom the PAYROLL role has SQL> -- been granted. Grant EXECUTE privilege on module LEAVE_ADJUSTMENT SQL> -- only to those employees who have been granted both the PAYROLL SQL> -- and ANNUAL_LEAVE roles. SQL> GRANT EXECUTE ON MODULE PAYROLL_UTILITIES TO PAYROLL; SQL> GRANT ALL ON TABLE SALARY_HISTORY TO PAYROLL; SQL> GRANT EXECUTE ON MODULE LEAVE_ADJUSTMENT cont> to PAYROLL, ANNUAL_LEAVE; SQL> -- User STUART joins the personnel department. Grant him SQL> -- the PAYROLL and ANNUAL_LEAVE roles so that he can SQL> -- perform all functions in the payroll department. SQL> CREATE USER STUART cont> IDENTIFIED EXTERNALLY SQL> GRANT PAYROLL, ANNUAL_LEAVE TO STUART; SQL> -- User STUART is promoted to supervisor and thus SQL> -- no longer needs access to the objects controlled by SQL> -- the ANNUAL_LEAVE role. Revoke that role from user SQL> -- STUART. SQL> REVOKE ANNUAL_LEAVE FROM STUART;