例6-2は、ALTER DICTIONARY句を使用したINTEGRATE文を発行することにより、ソースとしてデータベース・ファイルを使用したリポジトリの更新方法を示しています。 この例は、データベース・ファイルの定義と一致しているリポジトリの定義で開始されます。データベースには1つの表があり、リポジトリには1つのレコードがあります。この表とレコードはともにCUSTOMER_ORDERSと呼ばれます。CUSTOMER_ORDERS表は4つの列で構成され、各列はその同じ名前の4つのドメイン(FIRST_ORDER、SECOND_ORDER、THIRD_ORDER、FOURTH_ORDER)に基づいています。
この例では、データベース・ファイルにドメインFIFTH_DOMを追加します。このドメインにはローカル列FIFTH_ORDERが基づいています。この時点で、データベース・ファイルとリポジトリの定義は一致しなくなります。INTEGRATE ... ALTER DICTIONARY文は、ソースとしてデータベース・ファイル定義を使用してリポジトリを変更することにより、この状況を解決します。
例6-2 ALTER DICTIONARY句とともにINTEGRATE文を使用したリポジトリ定義の変更 |
---|
SQL> ! Create the database using the PATHNAME clause: SQL> ! SQL> CREATE DATABASE FILENAME TEST1 cont> PATHNAME SYS$COMMON:[REPOSITORY]TEST1; SQL> ! SQL> ! Create domains for the TEST1 database: SQL> ! SQL> CREATE DOMAIN FIRST_ORDER CHAR(4); SQL> CREATE DOMAIN SECOND_ORDER CHAR(4); SQL> CREATE DOMAIN THIRD_ORDER CHAR(4); SQL> CREATE DOMAIN FOURTH_ORDER CHAR(4); SQL> CREATE TABLE CUSTOMER_ORDERS cont> (FIRST_ORDER FIRST_ORDER, cont> SECOND_ORDER SECOND_ORDER, cont> THIRD_ORDER THIRD_ORDER, cont> FOURTH_ORDER FOURTH_ORDER); SQL> COMMIT; SQL> DISCONNECT DEFAULT; SQL> ! SQL> ! Attach to the database with the FILENAME clause so the SQL> ! repository is not updated: SQL> ! SQL> ATTACH 'ALIAS TEST1 FILENAME TEST1'; SQL> ! SQL> ! Use the SHOW TABLE statement to see what columns and domains SQL> ! are part of the table CUSTOMER_ORDERS: SQL> ! SQL> SHOW TABLE (COLUMNS) TEST1.CUSTOMER_ORDERS; Information on table TEST1.CUSTOMER_ORDERS Columns for table TEST1.CUSTOMER_ORDERS: Column Name Data Type Domain ----------- --------- ------ FIRST_ORDER CHAR(4) FIRST_ORDER SECOND_ORDER CHAR(4) SECOND_ORDER THIRD_ORDER CHAR(4) THIRD_ORDER FOURTH_ORDER CHAR(4) FOURTH_ORDER SQL> ! SQL> ! Create a new domain called FIFTH_DOM. Add a new SQL> ! column to the CUSTOMER_ORDERS table called FIFTH_ORDER SQL> ! and base it on the domain FIFTH_DOM: SQL> ! SQL> CREATE DOMAIN TEST1.FIFTH_DOM CHAR(4); SQL> ALTER TABLE TEST1.CUSTOMER_ORDERS ADD FIFTH_ORDER TEST1.FIFTH_DOM; SQL> ! SQL> ! Check the CUSTOMER_ORDERS table to verify that the column FIFTH_ORDER SQL> ! was created: SQL> ! SQL> SHOW TABLE (COLUMNS) TEST1.CUSTOMER_ORDERS; Information on table TEST1.CUSTOMER_ORDERS Column Name Data Type Domain ----------- --------- ------ FIRST_ORDER CHAR(4) TEST1.FIRST_ORDER SECOND_ORDER CHAR(4) TEST1.SECOND_ORDER THIRD_ORDER CHAR(4) TEST1.THIRD_ORDER FOURTH_ORDER CHAR(4) TEST1.FOURTH_ORDER FIFTH_ORDER CHAR(4) TEST1.FIFTH_DOM SQL> COMMIT; SQL> EXIT $ ! $ ! Invoke CDO: $ ! $ REPOSITORY CDO> ! CDO> ! Note that only the database definition for TEST1 appears in the CDO> ! repository directory: CDO> ! DIRECTORY Directory SYS$COMMON:[REPOSITORY] TEST1(1) CDD$DATABASE CDO> ! CDO> ! Check the record CUSTOMER_ORDERS. The field FIFTH_ORDER is not part of CDO> ! the record CUSTOMER_ORDERS. This means that the definitions in the CDO> ! database file do not match the definitions in the repository. CDO> ! CDO> ! CDO> SHOW RECORD CUSTOMER_ORDERS FROM DATABASE TEST1 Definition of the record CUSTOMER_ORDERS | Contains field FIRST_ORDER | Contains field SECOND_ORDER | Contains field THIRD_ORDER | Contains field FOURTH_ORDER CDO> EXIT $ ! $ ! Enter SQL again: $ ! $ SQL SQL> ! SQL> ! To make the definitions in the repository match those in the database SQL> ! file, use the INTEGRATE statement with the ALTER DICTIONARY clause. SQL> ! Note that the INTEGRATE statement implicitly attaches to the SQL> ! database. SQL> ! SQL> INTEGRATE DATABASE PATHNAME TEST1 ALTER DICTIONARY; SQL> COMMIT; SQL> EXIT $ ! $ ! Enter CDO again: $ ! $ REPOSITORY CDO> ! CDO> ! Use the SHOW RECORD command to verify that the field FIFTH_ORDER is now CDO> ! part of the record CUSTOMER_ORDERS. Now, the definitions in both the CDO> ! repository and the database file are the same. CDO> ! CDO> SHOW RECORD CUSTOMER_ORDERS FROM DATABASE TEST1 Definition of record CUSTOMER_ORDERS | Contains field FIRST_ORDER | Contains field SECOND_ORDER | Contains field THIRD_ORDER | Contains field FOURTH_ORDER | Contains field FIFTH_ORDER CDO> ! CDO> ! Use the ENTER command to make the record (table) CUSTOMER_ORDERS and CDO> ! its fields (domains) appear in the repository. The ENTER command CDO> ! assigns a repository directory name to an element. CDO> ! CDO> ENTER FIELD FIRST_ORDER FROM DATABASE TEST1 CDO> ! CDO> ! Verify that a repository path name was assigned to the field CDO> ! FIRST_ORDER: CDO> ! CDO> DIRECTORY Directory SYS$COMMON:[REPOSITORY] FIRST_ORDER(1) FIELD TEST1(1) CDD$DATABASE CDO> ENTER FIELD SECOND_ORDER FROM DATABASE TEST1 . . . CDO> ENTER FIELD FIFTH_DOM FROM DATABASE TEST1 CDO> ! CDO> ! Now all the domains and tables in TEST1 have been assigned a CDO> ! repository directory name: CDO> DIRECTORY Directory SYS$COMMON:[REPOSITORY] CUSTOMER_ORDERS(1) RECORD FIFTH_DOM(1) FIELD FIRST_ORDER(1) FIELD FOURTH_ORDER(1) FIELD SECOND_ORDER(1) FIELD TEST1(1) CDD$DATABASE THIRD_ORDER(1) FIELD |
既存のデータベース・ファイルの定義を初めてリポジトリに格納するには、CREATE PATHNAME句とともにINTEGRATE文を使用します。この文は、ソースとしてデータベース・ファイルを使用してリポジトリ定義を作成します。
例6-3は、既存のデータベース・システム・ファイルの定義を初めてリポジトリに格納する方法を示しています。この例では、最初にリポジトリではなくデータベース・ファイルでのみデータベースを作成します。次に、INTEGRATE文でCREATE PATHNAME句を使用して、データベース・システム・ファイルのデータ定義でリポジトリを更新します。
例6-3 リポジトリへの既存のデータベース・ファイルの定義の格納 |
---|
SQL> ! SQL> ! Create a database without requiring the repository (the default) SQL> ! or specifying a path name: SQL> ! SQL> CREATE DATABASE ALIAS DOGS; SQL> ! SQL> ! Now create a table for the breed of dog, poodles. The SQL> ! columns in the table are types of poodles: SQL> ! SQL> CREATE TABLE DOGS.POODLES cont> ( STANDARD CHAR(10), cont> MINIATURE CHAR(10), cont> TOY CHAR(10) ); SQL> ! SQL> ! Use the SHOW TABLE statement to see the table POODLES: SQL> ! SQL> SHOW TABLE (COLUMNS) DOGS.POODLES Information on table DOGS.POODLES Columns for table DOGS.POODLES: Column Name Data Type Domain ----------- --------- ------ STANDARD CHAR(10) MINIATURE CHAR(10) TOY CHAR(10) SQL> COMMIT; SQL> EXIT $ ! $ ! Enter CDO: $ ! $ REPOSITORY CDO> ! CDO> ! Use the DIRECTORY command to check if the database definition DOGS is CDO> ! in the repository: CDO> ! CDO> DIRECTORY Directory SYS$COMMON:[REPOSITORY] %CDO-E-NOTFOUND, entity not found in dictionary CDO> ! CDO> ! DOGS is not in the repository. CDO> ! CDO> EXIT $ ! $ ! Enter SQL again: $ ! $ SQL SQL> ! SQL> ! Use the INTEGRATE statement using the CREATE PATHNAME clause to SQL> ! update the repository using the DOGS database file: SQL> ! SQL> INTEGRATE DATABASE FILENAME SQL_USER:[PRODUCTION.ANIMALS]DOGS cont> CREATE PATHNAME SYS$COMMON:[REPOSITORY]DOGS; SQL> COMMIT; SQL> EXIT $ ! $ ! Enter CDO again: $ ! $ REPOSITORY CDO> ! CDO> ! Use the DIRECTORY command to check if the database definition DOGS CDO> ! has been integrated into the repository: CDO> ! CDO> DIRECTORY Directory SYS$COMMON:[REPOSITORY] DOGS(1) CDD$DATABASE CDO> ! CDO> ! You can also use the SHOW USED_BY command to see CDO> ! if the record (table) POODLES and the fields (columns) CDO> ! STANDARD, MINIATURE, and TOY are part of the database CDO> ! definition DOGS. CDO> ! CDO> SHOW USED_BY/FULL DOGS Members of SYS$COMMON:[REPOSITORY]DOGS(1) | DOGS (Type : CDD$RDB_DATABASE) | | via CDD$DATABASE_SCHEMA . . . | SYS$COMMON:[REPOSITORY]CDD$RDB_SYSTEM_METADATA.RDB$CDD_NAME;1(Type : FIELD) | | | | via CDD$DATA_AGGREGATE_CONTAINS | | POODLES (Type : RECORD) | | | via CDD$RDB_DATA_AGGREGATE | | | STANDARD (Type : FIELD) | | | | via CDD$DATA_AGGREGATE_CONTAINS | | | | SQL$10CHR (Type : FIELD) | | | | | via CDD$DATA_ELEMENT_BASED_ON | | | MINIATURE (Type : FIELD) | | | | via CDD$DATA_AGGREGATE_CONTAINS | | | | SQL$10CHR (Type : FIELD) | | | | | via CDD$DATA_ELEMENT_BASED_ON | | | TOY (Type : FIELD) | | | | via CDD$DATA_AGGREGATE_CONTAINS | | | | SQL$10CHR (Type : FIELD) | | | | | via CDD$DATA_ELEMENT_BASED_ON . . . CDO> EXIT |
例6-4は、ALTER DICTIONARY句を使用したINTEGRATE DOMAIN文を発行することにより、ソースとしてデータベース・ファイルを使用したリポジトリ・フィールドの更新方法を示しています。 この例は、データベース・ファイルの定義と一致しているリポジトリの定義で開始されます。データベースには1つのドメインがあり、リポジトリには1つのフィールドがあります。このドメインとフィールドはともにDOMTESTと呼ばれます。
この例では、データベース・ファイル名がTESTDBのドメインを変更します。この時点で、データベース・ファイルとリポジトリの定義は一致しなくなります。INTEGRATE DOMAIN ... ALTER DICTIONARY文は、ソースとしてデータベース・ファイル定義を使用してリポジトリを変更することにより、この状況を解決します。
例6-4 ALTER DICTIONARY句とともにINTEGRATE DOMAIN文を使用したリポジトリ・フィールドの変更 |
---|
SQL> -- Create a database, domain, and table. SQL> -- SQL> CREATE DATABASE FILENAME TESTDB PATHNAME TESTDB; SQL> CREATE COLLATING SEQUENCE FRENCH FRENCH; SQL> CREATE DOMAIN DOMTEST cont> CHAR(5) cont> COLLATING SEQUENCE IS FRENCH; SQL> CREATE DOMAIN TEST_DOM_1 cont> CHAR(1); SQL> CREATE TABLE TEMP_TAB cont> (ROW1 CHAR(5), cont> ROW2 DOMTEST, cont> ROW3 TEST_DOM_1, cont> ROW4 INT); SQL> COMMIT; SQL> SHOW DOMAIN DOMTEST DOMTEST CHAR(5) Collating sequence: FRENCH SQL> -- SQL> -- Disconnect from the database and invoke Oracle CDD/Repository SQL> -- user interface and show the field DOMTEST from the TESTDB SQL> -- database. SQL> -- SQL> DISCONNECT ALL; SQL> EXIT $ CDO CDO> SHOW FIELD DOMTEST FROM DATABASE TESTDB Definition of field DOMTEST | Datatype text size is 5 characters | Collating sequence 'FRENCH' CDO> ! CDO> ! Exit from Oracle CDD/Repository and attach to the database by file name CDO> ! only. CDO> ! CDO> EXIT SQL> ATTACH 'FILENAME TESTDB'; SQL> -- SQL> -- Alter the domain DOMTEST. SQL> -- SQL> ALTER DOMAIN DOMTEST cont> CHAR(10) cont> COLLATING SEQUENCE IS FRENCH; SQL> COMMIT; SQL> SHOW DOMAIN DOMTEST DOMTEST CHAR(10) Collating sequence: FRENCH SQL> -- SQL> -- Disconnect from the database and attach by path name only to issue SQL> -- the INTEGRATE DOMAIN statement. SQL> -- SQL> DISCONNECT ALL; SQL> ATTACH 'PATHNAME TESTDB'; SQL> INTEGRATE DOMAIN DOMTEST ALTER DICTIONARY; SQL> COMMIT; SQL> -- SQL> -- Disconnect from the database and invoke Oracle CDD/Repository V6.1 SQL> -- user interface and show the altered field DOMTEST from the TESTDB SQL> -- database. SQL> -- SQL> DISCONNECT ALL; SQL> EXIT $ CDO CDO> SHOW FIELD DOMTEST FROM DATABASE TESTDB Definition of field DOMTEST | Datatype text size is 10 characters | Collating sequence 'FRENCH' | Generic CDD$DATA_ELEMENT_CHARSET is '0' |
ループの現在の反復を中断および次の反復を開始またはループを終了(終了条件によって異なる)します。
複数文プロシージャの複合文のITERATE制御文は、次の環境で使用できます。
- 対話型SQL内
- プリコンパイル対象のホスト言語プログラムに埋め込まれる場合
- SQLモジュールのプロシージャの一部として
- 動的SQLで動的に実行される文として
statement-label
複合文またはループ文に割り当てられたラベルを指定します。
- 文のラベルは、アクティブな反復ループ文で使用する必要があります。反復ループ文には、LOOP文、FORカーソル・ループ文、FORカウント・ループ文、WHILE文およびREPEAT文が含まれます。指定したラベルが不明、アクティブでない、または反復文のラベルでない場合には、例外が発生します。
- 文のラベルが省略された場合、最も内側の反復文がデフォルトで使用されます。アクティブな反復文がない場合、例外が発生します。
例1: ITERATE制御文の使用
次の例は、FORカーソル・ループの現在の行の処理を早期に完了するために使用されるITERATE制御文を示しています。
SQL> BEGIN cont> FOR :ord AS TABLE CURSOR ord_cursor cont> AS SELECT * FROM orders WHERE customer_id = :cid cont> DO cont> IF stock_count (:ord.product_id, :ord.quantity) IS NULL THEN cont> ITERATE; cont> END IF; cont> -- transfer stock to this order cont> UPDATE stock SET on_hand = on_hand - :ord.quantity cont> WHERE product_id = :ord.product_id; cont> UPDATE orders SET :ord.available = :ord.quantity cont> WHERE CURRENT OF ord_cursor; cont> END FOR; cont> END;
複合文ブロック内またはループ文内で無条件に実行を終了しますが、終了した文の直後のSQL文の実行を再開します。
LEAVE制御文は、次の環境の複合文で使用できます。
- 対話型SQL内
- プリコンパイル対象のホスト言語プログラムに埋め込まれる場合
- SQLモジュールのプロシージャの一部として
- 動的SQLで動的に実行される文として
statement-label
複合文、ループ文または複数文プロシージャに割り当てられたラベルを指定します。
- プロシージャに含まれる複合文がラベル付けされていない場合、LEAVE文はそのプロシージャの名前を指定できます。詳細は、「複合文」を参照してください。
- 文のラベルを省略すると、LEAVE文は、現在アクティブなループ文(WHILE、LOOP、REPEAT、FORカーソル・ループ、FORカウント・ループ)を終了します。文のラベルを省略しない場合、LEAVE文は、ラベル付けされた現在の文を終了します。アクティブなループ文またはラベル付けされた文がない場合は、現在のプロシージャが終了します。
- LEAVE文を使用してSQLファンクションを終了しないでください。ファンクションでは結果が返される必要があります。LEAVE文を使用してファンクションを終了しようとすると、ランタイム・エラーが表示されます。かわりにRETURN文を使用してください。
例1: ループ内でのLEAVE制御文の使用
SQL> set flags 'trace'; SQL> SQL> create module REPORTS cont> /* ***> This procedure counts the employees of a given state ***> who have had a decrease in their salary during their ***> employment ***> */ cont> procedure COUNT_DECREASED cont> (in :state CHAR(2) cont> ,inout :n_decreased INTEGER); cont> begin cont> set :n_decreased = 0; cont> cont> EMP_LOOP: cont> for :empfor cont> as each row of cont> select employee_id cont> from EMPLOYEES where state = :state cont> do cont> begin cont> declare :last_salary INTEGER (2) default 0; cont> cont> HISTORY_LOOP: cont> for :salfor cont> as each row of cont> select salary_amount cont> from SALARY_HISTORY cont> where employee_id = :empfor.employee_id cont> order by salary_start cont> do cont> if :salfor.salary_amount < :last_salary cont> then cont> set :n_decreased = :n_decreased + 1; cont> trace :empfor.employee_id, ': ', :salfor.salary_amount; cont> leave HISTORY_LOOP; cont> end if; cont> cont> set :last_salary = :salfor.salary_amount; cont> end for; cont> end; cont> end for; cont> end; cont> cont> end module; SQL> SQL> declare :n integer; SQL> call COUNT_DECREASED ('NH', :n); ~Xt: 00200: 40789.00 ~Xt: 00248: 46000.00 ~Xt: 00471: 52000.00 N 3 SQL> SQL> rollback;
例2: 複合文の実行の終了
PROCEDURE SAMPLE (IN :ID MONEY); BEGIN DECLARE: AMOUNT MONEY (SELECT TOTAL_AMOUNT FROM M_TABLE); LOOP IF :AMOUNT IS NULL THEN LEAVE; END IF; . . . SET :AMOUNT =:AMOUNT-100.00; IF :AMOUNT < 0.00 THEN LEAVE; END IF; END LOOP; END;
特定のロック・モードで用意され、現在のトランザクション用に予約された表のリストに追加される表のリストを指定します。ビューが指定されている場合は、そのビューで参照される実表が指定されたロック・モードでロックされます。
LOCK TABLE文は、複数文プロシージャの複合文で次のような場合に使用できます。
- 対話型SQL内
- ホスト言語プログラムに埋め込まれる場合
- SQLモジュールまたはその他の複合文のプロシージャの一部として
- 動的SQLで動的に実行される文として
DATA DEFINITION
READ
WRITE
これらの引数の詳細は、「SET TRANSACTION文」を参照してください。IN lock-mode MODE
FOR lock-mode MODE
指定した表およびビューで使用するロック・モードを指定します。INキーワードとFORキーワードはシノニムです。表ロック・モードは昇格できますが、降格できません。たとえば、SHARED READロックはSHARED WRITEに昇格できますが、SHARED WRITEモードはSHARED READモードに降格できません。LOCK TABLE文とSET TRANSACTION文およびDECLARE TRANSACTION文の相互作用の詳細は、「使用方法」を参照してください。SHARED
PROTECTED
EXCLUSIVE
これらの引数の詳細は、「SET TRANSACTION文」を参照してください。table-name
ロックおよび予約する、データベースに現存している1つ以上の表またはビューの名前です。GLOBALまたはLOCAL TEMPORARY TABLESとして作成した表の指定は可能ですが、これらのタイプの表には共有データが含まれず、ロックされないため、これらの表は無視されます。表名の接頭辞として別名を使用すると、複数のデータベースの表を指定できます。別名を指定しない場合は、デフォルトの別名が使用されます。WAIT
NOWAIT
DEFAULT WAIT
ロックされた表が出現したときのLOCK TABLE文の処理内容を指定します。WAITを指定すると、この文は他のトランザクションが完了するまで待機してから続行されます。NOWAITを指定すると、トランザクションでロックされた表が出現したときにエラー・メッセージが返されます。DEFAULT WAITを指定すると、現在のトランザクションで指定されたロック・モードが使用されます。指定したロック・モードがトランザクションで指定されたものと異なる場合は、LOCK TABLE文を使用して指定したロック・モードが優先されます。ただし、その表がすでに予約されている場合は除きます。デフォルトはWAIT句です。
- LOCK TABLE文には、SET TRANSACTION RESERVING句よりも明らかな利点があります。表のアクセスが実行時まで決定しない場合、LOCK TABLE文では、SHARED READ以外のモードで表をロックできます。たとえば、複雑なアプリケーションや動的なアプリケーションでは、トランザクションの開始時にアクセス対象の表の名前が不明な場合があります。LOCK TABLE文は、これらのアプリケーションがトランザクションの開始後、表の名前が判明したときに表を追加できるようにします。
- RESERVING句を含むSET TRANSACTION文またはDECLARE TRANSACTION文でトランザクションを開始した場合は、そのトランザクション中に参照されるすべての表がそのトランザクションの予約リストで指定されているか、その後、LOCK TABLE文を使用して指定する必要があります。このルールの例外は、一時表と、制約およびトリガーによって参照される表です。これらの表は、そのアクセス特性に従って自動的に予約されます。たとえば、制約では読取りアクセスを必要とし、トリガーでは書込みアクセスを必要とし、一時表では特別なロックを必要としません。
- 予約された表のリストを指定せずにトランザクションを開始した場合は、そのトランザクション中に任意の表を参照できます。デフォルトでは、発行されるアクセス文のタイプによってSHARED READまたはSHARED WRITEが表のアクセスに適用されます。LOCK TABLE文を使用すると、必要な場合にトランザクションによってデフォルトのロック動作を調整できます。
- トランザクションで複数のLOCK TABLE文を使用すると、任意の順序でいつでも自由に表を予約できます。ただし、この場合は同時実行の環境でデッドロックが発生する場合があります。慎重に設計することにより、このような問題を排除するか、最小限に抑えることができます。(これは、RESERVING句とともにSET TRANSACTION文を使用した場合の動作と対照的です。この場合、RDB$RELATIONシステム・リレーションのRDB$RELATION_ID列で指定された順序で表が予約されるため、すべてのアプリケーションで一貫性のある順序付けが使用されます。これにより、表の予約時のデッドロックが回避または排除されます。)
- アクティブなトランザクションがない場合にLOCK TABLE文を発行すると、デフォルトのトランザクションが暗黙的に開始されます。
- LOCK TABLE文が表に設定したロックは、COMMIT文、ROLLBACK文またはDISCONNECT文でトランザクションを終了すると解除されます。
例1: READ MODEによる表のロック
SQL> LOCK TABLE EMPLOYEES IN PROTECTED READ MODE NOWAIT;
例2: 異なるモードによる2つの表のロック
SQL> LOCK TABLE DB1.JOB_HISTORY IN SHARED WRITE MODE, cont> DB2.SALARY_HISTORY IN EXCLUSIVE WRITE MODE;