準備された文に関する情報をSQL記述子領域(SQLDA)に書き込みます。DESCRIBE文は動的SQL文です。動的SQLでは、プリコンパイルされたプログラムのソース・コードまたはSQLモジュール言語プロシージャの一部であるSQL文とは対照的に、プログラムは実行時にSQL文を受け入れたり生成できます。プリコンパイルされたSQLまたはSQLモジュール言語文とは異なり、動的に実行されるこのようなSQL文は、プログラムのソース・コードの一部ではなく、プログラムの実行中に生成されます。動的SQLは、プログラムで処理する必要があるSQL文のタイプを予測できない場合に便利です。
SQLDAは、動的SQLプログラムでのみ使用されるホスト言語変数のコレクションです。SQLDAを使用するには、ホスト言語がポインタ変数をサポートする必要があります。ポインタ変数では、ホスト言語変数に直接データを格納するのではなくデータのアドレスを格納して記憶域に間接的にアクセスします。ポインタ変数のサポートも行うSQLプリコンパイラによってサポートされる言語は、Ada、CおよびPL/Iです。ポインタ変数をサポートするその他の言語はSQLDAを使用できますが、ソース・コードに直接SQL文を埋め込むのではなく、SQL文を含むSQLモジュール・プロシージャをコールする必要があります。SQLDAでは、動的SQL文の情報をプログラムに、そのプログラムによって割り当てられたメモリーの情報をSQLに提供します。
DESCRIBE文は、プログラムが使用する情報をSQLがSQLDAに書き込む方法を指定します。具体的には、DESCRIBE文は、準備された文の選択リスト項目またはパラメータ・マーカーの、数とデータ型をSQLDAに格納します。
付録Dには、SQLDAの特定のフィールドの詳細と、プログラムがSQLDAを使用して、準備された文の選択リスト項目およびパラメータ・マーカーと通信する方法の詳細が記載されています。
DESCRIBE文は次の環境で使用できます。
- プリコンパイル対象のホスト言語プログラムに埋め込まれる場合
- SQLモジュールのプロシージャの一部として
INTO descriptor-name
SQLが選択リスト項目または入出力パラメータ・マーカーの情報を書き込むSQLDAとして、ホスト言語プログラムで宣言された構造体の名前を指定します。プリコンパイルされたプログラムは、埋込みSQL文のINCLUDE SQLDAを使用して、プログラムのプリコンパイル時に、SQLDAと呼ばれるSQLDA構造体の宣言をプログラムに自動的に挿入できます。SQLモジュール言語を使用するプログラムは、SQLDAを明示的に宣言する必要があります。プリコンパイルされたプログラムまたはSQLモジュール言語プログラムは、追加のSQLDAを明示的に宣言できますが、SQLDAはそれぞれ一意の名前で宣言する必要があります。SQLDA構造体のサンプル宣言は、付録D.3節を参照してください。
MARKERS
INPUT
DESCRIBE文が入力パラメータ・マーカーの情報をSQLDAに書き込むことを指定します。MARKERS句およびINPUT句は、DESCRIBE文が準備された文の入力パラメータ・マーカーの数とデータ型に関する情報をSQLDAに書き込むことを指定します。準備された文の入力パラメータ・マーカーは、非動的な埋込みSQL文のホスト言語変数と同じ目的を果します。プログラムでは、SQLDAのその情報を使用して記憶域を割り当てることができます。プログラムではその割り当てられた記憶域に値を指定する必要があります。SQLでは、準備された文を動的に実行する場合に、その値をパラメータ・マーカーの代替として使用します。
SELECT LIST
OUTPUT
DESCRIBE文が準備された文の戻り値に関する情報をSQLDAに書き込むことを指定します。この句を使用する場合、DESCRIBE文は準備された文の戻り値の数とデータ型に関する情報をSQLDAに書き込みます。プログラムでは、その情報を使用して戻り値に対して記憶域を割り当てることができます。プログラムによって割り当てられた記憶域では、戻り値を受け取ります。次の文または句はDESCRIBE文に値を返します。
- SELECT文の選択リスト項目
- 複数文プロシージャ内の次の文
- シングルトンSELECT文
- INSERT...RETURNING文およびUPDATE...RETURNING文
- SET代入文
- (ストアド・プロシージャを起動する)CALL文
- 動的シングルトンSELECT文
デフォルトはSELECT LIST(またはOUTPUT)です。
statement-name
statement-id-parameter
準備された文の名前を指定します。動的に実行される文に対するPREPARE文がパラメータを指定する場合、DESCRIBE文で明示的な文名ではなく同じパラメータを使用します。パラメータまたはコンパイル時の文名を指定できます。パラメータを指定すると、SQLは実行時にプログラムの識別子を設定します。SQLが返した文識別子を含むには、整数パラメータを使用します。SQLに渡す文の名前を含むには、文字列パラメータを使用します。詳細は、「PREPARE文」および「DECLARE CURSOR文、動的」を参照してください。
例1: 準備されたSELECT文でのDESCRIBE...OUTPUT文の使用
このPL/Iプログラムは、DESCRIBE...OUTPUT文を使用した、準備されたSELECT文の選択リスト項目に関する情報のSQLDAへの書込みを示しています。この特定の準備されたSELECT文にはパラメータ・マーカーはありません。
DESCRIBE文の発行後、プログラムではSQLDAにホスト言語変数のアドレスを格納します。この変数はFETCH文の実行時に結果表の列の値を受け取ります。
例を短くするため、このPL/Iプログラムは次のように簡略化されています。
- プログラムには、直接PREPARE文で動的に実行されるソース・コードの一部としてSELECT文が含まれています。このようなコーディングされたSQL文を含むプログラムでは、動的SQLの使用をまったく必要とせず、SELECT文をDECLARE CURSOR文にそのまま埋め込むことができます。(実行時に生成されるSQL文の処理を必要とするプログラムは、動的SQLを要求するタイプのみです。)
- プログラムは、選択リスト項目に対するホスト言語変数を宣言します。その際、SQLDAのこれらの項目の記述はチェックしません。通常、アプリケーションは、記憶域を割り当てる前に、SQLDAを調べて準備されたSELECT文によって生成された選択リスト項目の数とデータ型を確認する必要があります。
- プログラムでは、この動的に実行されるSELECT文にパラメータ・マーカーが存在するかどうかを調べる場合にDESCRIBE...INPUT文は使用されません。この例では、プログラムでSELECT文がコーディングされているため、DESCRIBE...INPUT文の必要がないことは明らかです。ただし、実行時にSELECT文が生成された場合、プログラムでDESCRIBE...INPUT文を発行し、SQLDAのSQLDフィールドの値を確認してパラメータ・マーカーが存在するかどうかを確認する必要がある場合もあります。
CURSOR_EX : PROCEDURE OPTIONS (MAIN); /* * Illustrate the DESCRIBE...SELECT LIST statement using a * dynamic SELECT statement: * * Use a dynamic SELECT statement as the basis for * a cursor that displays a join of the EMPLOYEES * and SALARY_HISTORY tables on the screen. */ declare sys$putmsg external entry (any, any value, any value, any value); /* Declare SQL Communications Area: */ EXEC SQL INCLUDE SQLCA; /* Declare SQL Descriptor Area: */ EXEC SQL INCLUDE SQLDA; /* Declare the alias: */ EXEC SQL DECLARE ALIAS FILENAME 'SQL$DATABASE'; /* * Branch to ERR_HANDLER if the SQLCODE field * of the SQLCA is greater than 0: */ EXEC SQL WHENEVER SQLERROR GOTO ERR_HANDLER; /* * Declare a cursor named EMP that uses the * prepared statement DYN_SELECT: */ EXEC SQL DECLARE EMP CURSOR FOR DYN_SELECT; /* Declare a host structure to receive * the results of FETCH statements: */ DCL 1 P_REC, 2 EMPLOYEE_ID CHAR(5), 2 FIRST_NAME CHAR(10), 2 LAST_NAME CHAR(14), 2 SALARY_AMOUNT FIXED BINARY(31); /* Allocate memory for the SQLDA and * set the value of its SQLN field: */ SQLSIZE = 10; ALLOCATE SQLDA SET (SQLDAPTR); SQLN = 10; /* Prepare the SELECT statement * for dynamic execution directly * from a statement string: */ EXEC SQL PREPARE DYN_SELECT FROM 'SELECT E.EMPLOYEE_ID, E.FIRST_NAME, E.LAST_NAME, S.SALARY_AMOUNT FROM EMPLOYEES E, SALARY_HISTORY S WHERE E.EMPLOYEE_ID = S.EMPLOYEE_ID AND S.SALARY_END IS NULL'; /* Write information about the * columns of the result table * of DYN_SELECT into the SQLDA: */ EXEC SQL DESCRIBE DYN_SELECT OUTPUT INTO SQLDA; /* * Assign the addresses of the host language * variables that will receive the values of the * fetched row to the SQLDATA field * of the SQLDA: */ SQLDATA(1) = ADDR( EMPLOYEE_ID ); SQLDATA(2) = ADDR( FIRST_NAME); SQLDATA(3) = ADDR( LAST_NAME ); SQLDATA(4) = ADDR( SALARY_AMOUNT); /* Open the cursor: */ EXEC SQL OPEN EMP; /* Fetch the first row of the result table. * SQL uses the addresses in the SQLDA * to store values from the table into * the host language variables. */ EXEC SQL FETCH EMP USING DESCRIPTOR SQLDA; PUT EDIT ('Current Salaries of Employees: ') (SKIP, A, SKIP(2)); /* While the SQLCODE field of the * SQLCA is not 100 (NOT_FOUND error): */ DO WHILE (SQLCA.SQLCODE = 0); /* Display the values from the host language variables: */ PUT SKIP EDIT (EMPLOYEE_ID, ' ', FIRST_NAME, ' ', LAST_NAME, ' ', SALARY_AMOUNT) (A, A, A, A, A, A, F(9)); /* Fetch another row of the result table: */ EXEC SQL FETCH EMP USING DESCRIPTOR SQLDA; END; /* Close the cursor: */ EXEC SQL CLOSE EMP; RETURN; ERR_HANDLER: PUT EDIT ('Unexpected error, SQLCODE is: ', SQLCA.SQLCODE) (skip, a, f(9)); CALL SYS$PUTMSG(RDB$MESSAGE_VECTOR, 0, 0, 0); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK; RETURN; END CURSOR_EX;
「DECLARE CURSOR文、動的」の例2も参照してください。
宣言されたデータベースからデタッチして、宣言で指定した別名を解放します。DISCONNECT文はまた、指定したトランザクションを終了して、これらのトランザクションの開始以降に実行した変更をすべて元に戻します。
DISCONNECT文は次の環境で使用できます。
- 対話型SQL内
- プリコンパイル対象のホスト言語プログラムに埋め込まれる場合
- SQLモジュールのプロシージャの一部として
- 動的SQLで動的に実行される文として
ALL
すべてのアクティブな接続を指定します。connection-name
アタッチされるデータベースのグループ(環境)とそれらを参照するデータベースおよび問合せ(セッション)間の関連に対する名前を指定します。接続名は次のように指定できます。
- 一重引用符で囲まれた文字列リテラル
- (モジュール言語の)パラメータ
- (プリコンパイルされたSQLの)変数
CURRENT
現在の接続を指定します。DEFAULT
デフォルトの接続を指定します。
- FINISH文のかわりにDISCONNECT DEFAULT文を使用します。FINISH文は廃止予定の構文です。DISCONNECT DEFAULT文では自動ロールバックが実行されるため、必ず保持する変更をコミットしてからDISCONNECT文を実行してください。
モジュール言語プロシージャでの切断の詳細は、『Oracle Rdb7 Guide to SQL Programming』を参照してください。- 特定のデータベースからのアタッチおよびデタッチの実行時に、SQL接続および明示的なコールをDECdtmサービスに使用して制御できます。DECdtmシステム・サービスの明示的なコールおよび各データベースとSQL接続の関連付けにより、他のデータベースにアタッチした状態で、別のデータベースからデタッチできます。詳細は、『Oracle Rdb7 Guide to Distributed Transactions』を参照してください。
例1: 対話型SQLでのDISCONNECT文の使用対話型SQLでのこの例では、DISCONNECT文で以前にアタッチしたデータベースと同じ別名のデータベースにアタッチできることを示しています(この例では別名はデフォルトです)。SHOW DATABASE文を使用してデータベース設定を表示します。
SQL> ATTACH 'FILENAME mypers'; SQL> -- SQL> ATTACH 'FILENAME mypers'; This alias has already been declared. Would you like to override this declaration (No)? no %SQL-F-DEFDBDEC, A database has already been declared with the default alias SQL> DISCONNECT DEFAULT; SQL> ATTACH 'FILENAME mypers';
例2: プリコンパイルされたSQLでのDISCONNECT文の使用
この例はサンプル・プログラムsql_connections.scからのものです。プログラムで接続を使用するには、プリコンパイラのコマンドラインにSQLOPTIONS=(CONNECT)修飾子を指定する必要があります。この例では、connection-nameに文字列リテラル'al'を指定するEXEC SQL DISCONNECT文と、キーワードALLおよびDEFAULTを指定するEXEC SQL DISCONNECT文を示しています。
#include <stdio.h> #include <string.h> #include <descrip.h> char employee_id1[6]; char last_name1[16]; char employee_id2[16]; char degree[14]; char employee_id3[16]; char supervisor[6]; char employee_id4[6]; char last_name4[15]; void sys$putmsg(); EXEC SQL INCLUDE SQLCA; EXEC SQL declare alias filename personnel; EXEC SQL declare alias_1 alias filename personnel; EXEC SQL declare alias_2 alias filename personnel; EXEC SQL declare alias_3 alias filename personnel; main() { printf("\n\n\n******* Disconnect from default ***************\n"); EXEC SQL disconnect default; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("\n\n\n"); printf("********* Establish CONNECTION 1 **********\n"); EXEC SQL connect to 'alias alias_1 filename personnel' as 'a1'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Insert a record **********\n"); EXEC SQL insert into alias_1.employees (employee_id, last_name) values ('00301','FELDMAN'); if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Retrieve the record **********\n"); EXEC SQL select employee_id, last_name into :employee_id1, :last_name1 from alias_1.employees where employee_id = '00301'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("\n\n\n"); printf ("Employee_id = %s\n",employee_id1); printf ("Last_name = %s\n",last_name1); printf("\n\n\n"); printf("********* Establish CONNECTION 2 **********\n"); EXEC SQL connect to 'alias alias_2 filename personnel' as 'a2'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Insert a record **********\n"); EXEC SQL insert into alias_2.degrees (employee_id, degree_field) values ('00901','MASTERS'); if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Retrieve the record **********\n"); EXEC SQL select employee_id, degree_field into :employee_id2, :degree from alias_2.degrees where employee_id = '00901'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("\n\n\n"); printf("Employee-id = %s\n",employee_id2); printf("Degree = %s\n",degree); printf("\n\n\n"); printf("********* Establish CONNECTION 3 **********\n"); EXEC SQL connect to 'alias alias_3 filename personnel' as 'a3'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Insert a record **********\n"); EXEC SQL insert into alias_3.job_history (employee_id, supervisor_id) values ('01501','Brown'); if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Retrieve the record **********\n"); EXEC SQL select employee_id, supervisor_id into :employee_id3, :supervisor from alias_3.job_history where employee_id = '01501'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("\n\n\n"); printf("Employee-id = %s\n",employee_id3); printf("Supervisor = %s\n ",supervisor); printf("\n\n\n"); printf("********* Establish CONNECTION DEFAULT **********\n"); EXEC SQL set connect default ; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Retrieve record with id 00164 **********\n"); EXEC SQL select employee_id, last_name into :employee_id4, :last_name4 from employees where employee_id = '00164'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("\n\n\n"); printf("Employee_id = %s\n",employee_id4); printf("Last_name = %s\n",last_name4); printf("\n\n\n"); printf("**** DISCONNECT, RECONNECT & TRY TO FIND RECORD *****\n"); strcpy(employee_id1," "); strcpy(last_name1," "); EXEC SQL disconnect 'a1'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); EXEC SQL connect to 'alias alias_1 filename personnel' as 'a1'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("********* Retrieve the record **********\n"); EXEC SQL select employee_id, last_name into :employee_id1, :last_name1 from alias_1.employees where employee_id = '00301'; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); printf("************** SHOULD DISPLAY NO RECORD **************\n"); printf("\n\n\n"); printf("employee_id = %s\n",employee_id1); printf("last_name = %s\n",last_name1); printf("\n\n\n"); printf("*************** DISCONNECT ALL CONNECTIONS ***************\n"); EXEC SQL disconnect all; if (SQLCA.SQLCODE != 0) SYS$PUTMSG(&RDB$MESSAGE_VECTOR,0,0,0); EXEC SQL rollback; }
データベース・オブジェクトを削除します。
次の注意事項は、DROP DATABASEを除くすべてのDROP文に適用されます。
- LIST、DEFAULTまたはRDB$SYSTEMのいずれかの記憶域が読取り専用に設定されている場合、DROP文を実行できません。最初にこれらの記憶域を読取り/書込みに設定する必要があります。一部のデータベースではRDB$SYSTEMもデフォルトになり、記憶域をリストする場合があります。
- マルチスキーマ・データベースの場合、IF EXISTS句が予想したように機能しない可能性があります。これはオブジェクトが、DROP文で指定されたものとは異なる可能性があるSTORED NAMEを使用して内部的に削除されるためです。現在、IF EXISTS句ではマルチスキーマ名とストアド名は同一とみなされています。
- DROP文は読取り/書込みトランザクションで実行する必要があります。アクティブなトランザクションがない場合にこの文を発行すると、SQLでは、直近のDECLARE TRANSACTION文で指定された特性を持つトランザクションが暗黙的に開始されます。
- DROP文は次が該当する場合に失敗します。
- 適用されるデータベースがDICTIONARY IS REQUIRED引数を使用して作成された場合。
- データベースがFILENAME引数を使用してアタッチされた場合。
このような場合、文を発行すると次のエラーが発生します。
%RDB-E-NO_META_UPDATE, metadata update failed -RDMS-F-CDDISREQ, CDD required for metadata updates is not being maintained
- DROP文が不明のデータベース・オブジェクトに使用された場合、エラーがレポートされます。不要なエラー・メッセージが表示されないようにするには、SQLコマンド・スクリプトでIF EXISTSを使用します。
指定したカタログ定義を削除します。カタログを削除するには、最初にカタログに含まれているスキーマおよび定義をすべて削除する必要があります。指定したカタログを参照する他の定義が存在する場合、その削除は失敗します。DROP CATALOG文では、削除するスキーマおよび定義がすべてリストされます。これらの定義を削除しない場合、文をロールバックできます。
DROP CATALOG文は次の環境で使用できます。
- 対話型SQL内
- プリコンパイル対象のホスト言語プログラムに埋め込まれる場合
- SQLモジュールのプロシージャの一部として
- 動的SQLで動的に実行される文として
alias.name-of-catalog
データベースにアタッチする名前を指定します。プログラムまたは対話型SQL文で複数のデータベースを参照している場合は、常にカタログ名を別名で修飾します。カタログ名とその別名はピリオドで区切り、修飾した名前は二重引用符で囲みます。カタログ名を別名で修飾するには、先にSET QUOTING RULES文を発行する必要があります。
CASCADE
RESTRICT
デフォルトで制限付き削除を実行します。カタログに含まれている定義をすべて削除する場合、DROP CATALOG CASCADE文を指定できます。catalog-name
モジュールのカタログ名を指定します。IF EXISTS
被参照オブジェクトがデータベースに存在しない場合に、SQLコマンド言語によってエラー・メッセージが表示されないようにします。
- マルチスキーマ・データベースからカタログを削除するには、DROPデータベース権限が必要です。
- 別のユーザーがカタログを使用して問合せを発行している場合、そのカタログは削除できません。カタログを削除する前に、ユーザーはDISCONNECT文でデータベースからデタッチする必要があります。
- カタログRDB$CATALOGは削除できません。
例1: カタログの削除次の文では、別名PERSONNEL_ALIASに関連付けられたカタログDEPT1を削除しています。
SQL> ATTACH 'ALIAS PERSONNEL_ALIAS FILENAME CORPORATE_DATA'; SQL> SET QUOTING RULES 'SQL99'; SQL> CREATE CATALOG "PERSONNEL_ALIAS.DEPT1"; SQL> SHOW CATALOG; Catalogs in database PERSONNEL_ALIAS "PERSONNEL_ALIAS.ADMINISTRATION" "PERSONNEL_ALIAS.RDB$CATALOG"" "PERSONNEL_ALIAS.DEPT1" SQL> DROP CATALOG "PERSONNEL_ALIAS.DEPT1"; SQL> SHOW CATALOG; Catalogs in database PERSONNEL_ALIAS "PERSONNEL_ALIAS.ADMINISTRATION" "PERSONNEL_ALIAS.RDB$CATALOG" SQL> DROP CATALOG "PERSONNEL_ALIAS.RDB$CATALOG"; %SQL-F-NODROPSYSCAT, Catalog "PERSONNEL_ALIAS.RDB$CATALOG" may not be dropped SQL>