| Oracle Database アプリケーション開発者ガイド-基礎編 10gリリース2(10.2) B19248-02 |
|
ネットワーク操作を実現し、動的なWebコンテンツを生成できる言語は、Javaのみではありません。PL/SQLには、データベースをWeb上で使用可能にし、業務上のデータをイントラネットでアクセス可能なものにする多くの機能があります。
この章の内容は次のとおりです。
この項の内容は次のとおりです。
一般的に、PL/SQLで作成されるWebアプリケーションは、HTTPを介してWebブラウザと対話するストアド・プロシージャの集合です。相互リンクされた一連の動的に作成されたHTMLページが、Webアプリケーションのユーザー・インタフェースになります。
PL/SQL Webアプリケーションのプログラムのフローは、CGI Perlスクリプトのプログラムのフローと類似しています。CGIスクリプトは、Webページを動的に作成するために開発者によく使用されますが、Oracle Databaseへのアクセスに使用するには最適ではない場合が多くあります。PL/SQLストアド・プロシージャを使用してWebコンテンツを配信すると、データベース処理が強化され、柔軟性が生まれます。たとえば、DML、動的SQLおよびカーソルを使用できます。また、各HTTPリクエストを処理するために新しいCGIプロセスを指定する際のプロセス・オーバーヘッドが発生しなくなります。
図11-1に、PL/SQL Webアプリケーションの一般的なプロセスを示します。
プロセスには次のようなステップがあります。
HTP.Printなどのサブプログラムにより、Webページが動的に生成されます。生成されるWebページは、データベースの内容や入力パラメータによって異なります。
Webブラウザベースのアプリケーションは、この項で説明するOracle Databaseコンポーネントを使用して、PL/SQLで完全に実装できます。
このPL/SQLパッケージのセットは、実行時にmod_plsqlによってコールされるストアド・プロシージャを使用可能にする汎用インタフェースです。
ブラウザのリクエストに対するレスポンスで、PL/SQLプロシージャはユーザー入力に従ってOracle Databaseのデータを更新または取得します。続いて、ストアド・プロシージャはブラウザに対するHTTPレスポンスを生成します。通常はダウンロード・ファイルまたはHTML表示になります。Web Toolkit APIを使用すると、ストアド・プロシージャで次のような処理を実行できます。
表11-1に、一般的に使用されるPL/SQL Toolkitパッケージを示します。
『Oracle Application Server mod_plsqlユーザーズ・ガイド』で説明しているように、mod_plsqlは、HTTP上でWebクライアント・リクエストをPL/SQLストアド・プロシージャにマップします。詳細は、このマニュアルを参照してください。
一般的に、PL/SQL Webアプリケーションでは、ファンクション・コールを使用して出力用の各HTMLタグを生成します。これらのファンクションは、Oracle Databaseに付属するPL/SQL Web Toolkitパッケージの一部になっています。例11-1に、各HTMLタグと対応するHTPファンクションをコールして簡単なHTMLページを生成する方法を示します。
CREATE OR REPLACE PROCEDURE html_page IS BEGIN HTP.HTMLOPEN; -- generates <HTML> HTP.HEADOPEN; -- generates <HEAD> HTP.TITLE('Title'); -- generates <TITLE>Hello</TITLE> HTP.HEADCLOSE; -- generates </HTML> -- generates <BODY TEXT="#000000" BGCOLOR="#FFFFFF"> HTP.BODYOPEN( cattributes => 'TEXT="#000000" BGCOLOR="#FFFFFF"'); -- generates <H1>Heading in the HTML File</H1> HTP.HEADER(1, 'Heading in the HTML File'); HTP.PARA; -- generates <P> HTP.PRINT('Some text in the HTML file.'); HTP.BODYCLOSE; -- generates </BODY> HTP.HTMLCLOSE; -- generates </HTML> END;
各タグに対応するファンクション・コールを作成するかわりに、HTP.PRINTファンクションを使用して、テキストとタグを両方とも印刷します。例11-2にこの方法を示します。
CREATE OR REPLACE PROCEDURE html_page2 IS BEGIN HTP.PRINT('<html>'); HTP.PRINT('<head>'); HTP.PRINT('<meta http-equiv="Content-Type" content="text/html">'); HTP.PRINT('<title>Title of the HTML File</title>'); HTP.PRINT('</head>'); HTP.PRINT('<body TEXT="#000000" BGCOLOR="#FFFFFF">'); HTP.PRINT('<h1>Heading in the HTML File</h1>'); HTP.PRINT('<p>Some text in the HTML file.'); HTP.PRINT('</body>'); HTP.PRINT('</html>'); END;
第12章「PL/SQL Server Pagesの開発」では、HTMLコンテンツを生成するための、PL/SQLを使用したその他の配信方法について説明しています。PL/SQL Server Pagesは既知のHTMLタグに基づいて構築することができ、一連のファンクション・コールを新たに習得する必要がありません。PL/SQL Server Pagesのセットとして作成されたアプリケーションでも、PL/SQL Web Toolkitのファンクションを使用して、次のことができます。
Webアプリケーションを様々な状況で有効に活用するには、対話性を十分に高め、ユーザーによる選択を可能にする必要があります。迅速さを求めるWeb閲覧者に対応するには、対話の能率をよくし、ユーザーが選択項目を簡単に指定できるように、過多な決定事項やデータ入力を避ける必要があります。
PL/SQL Webアプリケーションにパラメータを渡す主な方法は、次のとおりです。
Submit」ボタンをクリックすると、すべてのデータおよび選択項目がストアド・プロシージャに転送されます。
この項の内容は次のとおりです。
リスト・ボックスおよびドロップダウン・リストは、HTMLタグ(<SELECT>)を使用して実装されます。
選択項目の数を多くする、または複数の選択を可能にする必要がある場合は、リスト・ボックスを使用します。リスト・ボックスは、項目をアルファベット順に表示する場合に適しています。これによって、ユーザーは、すべての項目を読まなくても目的の項目を短時間で検索できます。
次の場合にドロップダウン・リストを使用します。
ドロップダウン・リストは、初めてアクセスするユーザーの注意を引き、選択項目を読ませることができます。選択項目および順序を固定することで、ユーザーはドロップダウン・リストから項目を選択するときの動作に慣れ、素早く選択できるようになります。例11-3に、簡単なドロップダウン・リストを示します。
<form> <select name="seasons"> <option value="winter">Winter <option value="spring">Spring <option value="summer">Summer <option value="fall">Fall </select>
ラジオ・ボタンによって、NULL値(グループ内のいずれのラジオ・ボタンもチェックされていない場合)、またはチェックされたラジオ・ボタンに指定されている値のいずれかが渡されます。
一連のラジオ・ボタンのデフォルト値を指定するには、INPUTタグの1つにCHECKED属性を含めるか、ストアド・プロシージャ内のパラメータにDEFAULT句を含めます。ラジオ・ボタンのグループを設定するときは、「どちらでもない」ことを示す選択項目を含める必要があります。これは、ラジオ・ボタンを一度選択すると、別のボタンを選択することはできますが、選択を完全に取り消すことができないためです。たとえば、あるユーザーが選択を行った後に、それが間違っていたことに気付くという状況を考慮して、「はい」および「いいえ」とともに「興味なし」または「わからない」という選択項目を含めます。
チェックボックスでは、ストアド・プロシージャがNULL値、単一の値、または複数の値を受け取る場合があるため、特別な処理が必要です。
同じNAME属性を持つすべてのチェックボックスによって、1つのチェックボックス・グループが形成されます。グループ内のいずれのチェックボックスもチェックされていない場合、ストアド・プロシージャは、対応するパラメータに対してNULL値を受け取ります。
グループ内のチェックボックスの1つがチェックされている場合、ストアド・プロシージャは単一のVARCHAR2パラメータを受け取ります。
グループ内の複数のチェックボックスがチェックされている場合、ストアド・プロシージャはPL/SQLのTABLE OF VARCHAR2データ型のパラメータを受け取ります。類似のデータ型を宣言するか、OWA_UTIL.IDENT_ARRなどの事前定義のデータ型を使用する必要があります。値を検索するには、次のようにループを使用します。
CREATE OR REPLACE PROCEDURE handle_checkboxes ( checkboxes owa_util.ident_arr ) AS BEGIN ... FOR i IN 1..checkboxes.count LOOP htp.print('<p>Checkbox value: ' || checkboxes(i)); END LOOP; ... END; / SHOW ERRORS;
入力フィールドでは、ユーザーが誤った形式のデータや範囲外のデータなどを入力する可能性があるため、最も厳密な妥当性チェックが必要です。可能な場合、動的HTMLまたはJavaを使用してクライアント側でデータの妥当性チェックを行い、ユーザーにかわって正しいフォーマットにするか、ユーザーに再入力を促します。
次に例を示します。
これらの妥当性チェックが常に成功するとはかぎらないため、このような状況に対応できるようにストアド・プロシージャをコーディングします。ユーザーが誤ったデータを入力したときに「Back」ボタンを押さなくて済むように、エラー・メッセージと他のすべての値が記入された元のフォームを、1つのページに表示します。
パスワードなどの機密性の高い情報の場合、入力フィールドの<INPUT TYPE=PASSWORD>という特殊なフォームによって、入力されたテキストが非表示になります。
たとえば、次のプロシージャは、入力として2つの文字列を受け入れます。このプロシージャが初めてコールされた場合、値を入力するための単純なフォームのプロンプトが表示されます。ユーザーが情報を送ると、同じプロシージャが再コールされ、入力が正しいかどうかが確認されます。入力が正しい場合、プロシージャは入力を処理します。正しくない場合、プロシージャは、再入力するためのプロンプトを、最初の値が入力された状態で表示します。
-- Store a name and associated zip code in the database. CREATE OR REPLACE PROCEDURE associate_name_with_zipcode ( name VARCHAR2 DEFAULT NULL, zip VARCHAR2 DEFAULT NULL ) AS booktitle VARCHAR2(256); BEGIN -- Both entry fields must contain a value. The zip code must be 6 characters. -- (In a real program you would perform more extensive checking.) IF name IS NOT NULL AND zip IS NOT NULL AND length(zip) = 6 THEN store_name_and_zipcode(name, zip); htp.print('<p>The person ' || name || ' has the zip code ' || zip || '.'); -- If the input was OK, we stop here and the user does not see the form again. RETURN; END IF; -- If some data was entered, but it is not correct, show the error message. IF (name IS NULL AND zip IS NOT NULL) OR (name IS NOT NULL AND zip IS NULL) OR (zip IS NOT NULL AND length(zip) != 6) THEN htp.print('<p><b>Please re-enter the data. Fill in all fields, and use a 6-digit zip code.</b>'); END IF; -- If the user has not entered any data, or entered bad data, prompt for -- input values. -- Make the form call the same procedure to check the input values. htp.formOpen( 'scott.associate_name_with_zipcode', 'GET'); htp.print('<p>Enter your name:</td>'); htp.print('<td valign=center><input type=text name=name value="' || name || '">'); htp.print('<p>Enter your zip code:</td>'); htp.print('<td valign=center><input type=text name=zip value="' || zip || '">'); htp.formSubmit(NULL, 'Submit'); htp.formClose; END; / SHOW ERRORS;
ユーザーが同じ選択項目を毎回指定しなくても、一連のストアド・プロシージャを介して情報を渡すには、ストアド・プロシージャをコールするフォームに非表示パラメータを含める方法があります。最初のストアド・プロシージャによって、このストアド・プロシージャで生成されたHTMLフォームにユーザー名などの情報が入力されます。非表示パラメータの値は、ユーザーがその値をラジオ・ボタンまたは入力フィールドを介して入力した場合と同様に、次のストアド・プロシージャに渡されます。
1つのストアド・プロシージャから別のプロシージャに情報を渡すには、次の方法もあります。
HTMLフォームを使用して、クライアント・システム上のファイルを選択し、これをサーバーに転送できます。ストアド・プロシージャにより、CLOB、BLOBまたは大量のデータを保持できるその他のデータ型として、データベースにファイルを挿入できます。
PL/SQL Web ToolkitおよびPL/SQL ゲートウェイには、アップロードされたファイルを保持する「ドキュメント表」の概念があります。
デフォルトでは、HTMLフォームには、データをHTMLフォームからストアド・プロシージャまたはCGIプログラムに転送するための送信(Submit)ボタンが必要です。このボタンには、「検索」や「登録」など任意の名前を指定できます。
1つのページに複数のフォームを挿入し、各フォームに独自のフォーム要素と送信(Submit)ボタンを設定できます。非表示パラメータのみで構成されるフォームも作成できます。このフォームでは、ユーザーはボタンをクリックする以外の選択は行いません。
JavaScriptなどのスクリプト言語を使用すると、送信ボタンを排除して、ドロップダウン・リストからの選択など、別のアクションに応答してフォームが送られるようにすることができます。この方法は、ユーザーが選択する項目が1つのみで、送信(Submit)ボタンで確認する手順が必要でない場合に最適です。
HTMLフォームが送られると、ストアド・プロシージャは、記入されていないフォーム要素に対してNULLパラメータを受け取ります。NULLパラメータの原因には、入力フィールドが空である、一連のチェックボックス、ラジオ・ボタンまたはリスト項目がチェックされていない、またはVALUEパラメータの値が""(空の引用符)である、などがあります。
クライアント側で実行する妥当性チェックの内容にかかわらず、常にストアド・プロシージャをコーディングして、いくつかのパラメータがNULLになる状況に対処します。
DEFAULT句を使用して、フォーム・パラメータが欠落した状態でストアド・プロシージャがコールされたときに発生する例外を回避します。数値に対するデフォルトは0(ゼロ)に設定できます(適切な場合)。ユーザーが実際に値を指定したかどうか確認するには、DEFAULT NULLを使用します。
DEFAULT NULLが宣言された入力パラメータ値を使用する前に、その値がNULLかどうかを確認します。
Webアプリケーションでは、状態(特定の時点における現行のデータ・セット)の概念が特に重要です。Webページを切り替えると状態情報が簡単に失われ、ユーザーに何度も同じ選択をさせることになる場合があります。
状態情報は、HTMLフォームを使用して動的Webページ間で渡されます。情報は一連の名前/値ペアとして渡され、ストアド・プロシージャのパラメータになります。
ユーザーが複数の選択をする必要がある場合、多くの選択項目から1つを選択する必要がある場合、または偶然に誤って選択することを回避することが重要な場合は、HTMLフォームを使用します。ユーザーは、すべての選択を行って、選択した項目を再確認すると、「Submit」ボタンを押して選択を決定します。それ以降のページでは、非表示パラメータ(<INPUT TYPE=HIDDEN>タグ)を含むフォームを使用して、これらの選択項目をページからページへと渡すことができます。
ユーザーが1つまたは2つの選択項目のみに関心がある場合、または選択事項がWebページ内に散在している場合、アクションをハイパーリンクとして表し、必要な名前/値ペアを問合せ文字列(URL内の「?」の後に続く部分)に含めることによって、ユーザーが送信(Submit)ボタンを簡単に見つけられるようにできます。
状態情報は、Oracle Application Serverおよびそのmod_oseモジュールを使用して保持することもできます。この方法では、状態情報をパッケージ変数に格納して、ユーザーがWebサイトを移動しても、情報を使用可能のままにできます。
PL/SQLの組込み機能が従来のデータベース処理およびプログラミング・ロジックに重点を置く一方で、Oracle Databaseでは、PL/SQLプログラマに対しインターネット・コンピューティングを可能にするパッケージを提供しています。
この項の内容は次のとおりです。
PL/SQLプログラムまたはストアド・プロシージャから電子メールを送信するには、UTL_SMTPパッケージを使用します。 このパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
次のコード例は、アプリケーションがSMTPパッケージを使用して電子メールを送信する方法を示します。このアプリケーションは、ポート25でSMTPサーバーに接続し、単純なテキスト・メッセージを送信します。
PROCEDURE send_test_message IS mailhost VARCHAR2(64) := 'mailhost.fictional-domain.com'; sender VARCHAR2(64) := 'me@fictional-domain.com'; recipient VARCHAR2(64) := 'you@fictional-domain.com'; mail_conn utl_smtp.connection; BEGIN mail_conn := utl_smtp.open_connection(mailhost, 25); utl_smtp.helo(mail_conn, mailhost); utl_smtp.mail(mail_conn, sender); utl_smtp.rcpt(mail_conn, recipient); -- If we had the message in a single string, we could collapse -- open_data(), write_data(), and close_data() into a single call to data(). utl_smtp.open_data(mail_conn); utl_smtp.write_data(mail_conn, 'This is a test message.' || chr(13)); utl_smtp.write_data(mail_conn, 'This is line 2.' || chr(13)); utl_smtp.close_data(mail_conn); utl_smtp.quit(mail_conn); EXCEPTION WHEN OTHERS THEN -- Insert error-handling code here NULL; END;
PL/SQLプログラムまたはストアド・プロシージャから、ローカル・マシンのホスト名または特定のホスト名のIPアドレスを判断するには、UTL_INADDRパッケージを使用します。 このパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。UTL_TCPパッケージへのコール結果を使用します。
ネットワーク上のマシンにTCP/IP接続をオープンして、対応するソケットへの読込みまたは書込みを行うには、UTL_TCPパッケージを使用します。 このパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
HTTP URLのコンテンツを取得するには、 UTL_HTTPパッケージを使用します。通常、コンテンツはHTMLのタグ付きテキスト形式ですが、プレーン・テキスト、JPEGイメージなど、Webサーバーからダウンロードできるファイルであればどのようなものでもかまいません。 このパッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。
UTL_HTTPパッケージを使用して、次の操作を実行できます。
GETメソッドまたはPOSTメソッドを介したCGIパラメータなど)の制御
UTL_URLパッケージのESCAPEファンクションおよびUNESCAPEファンクションを介した、UTL_HTTPに使用するURLの作成および解析
通常、開発者はJavaまたはPerlを使用してこれらの操作を行いますが、このパッケージではPL/SQLで同じ操作が実行できます。
CREATE OR REPLACE PROCEDURE show_url ( url IN VARCHAR2, username IN VARCHAR2 DEFAULT NULL, password IN VARCHAR2 DEFAULT NULL ) AS req utl_http.req; resp utl_http.resp; name VARCHAR2(256); value VARCHAR2(1024); data VARCHAR2(255); my_scheme VARCHAR2(256); my_realm VARCHAR2(256); my_proxy BOOLEAN; BEGIN -- When going through a firewall, pass requests through this host. -- Specify sites inside the firewall that don't need the proxy host. utl_http.set_proxy('proxy.my-company.com', 'corp.my-company.com'); -- Ask UTL_HTTP not to raise an exception for 4xx and 5xx status codes, -- rather than just returning the text of the error page. utl_http.set_response_error_check(FALSE); -- Begin retrieving this Web page. req := utl_http.begin_request(url); -- Identify ourselves. Some sites serve special pages for particular browsers. utl_http.set_header(req, 'User-Agent', 'Mozilla/4.0'); -- Specify a user ID and password for pages that require them. IF (username IS NOT NULL) THEN utl_http.set_authentication(req, username, password); END IF; BEGIN -- Start receiving the HTML text. resp := utl_http.get_response(req); -- Show the status codes and reason phrase of the response. dbms_output.put_line('HTTP response status code: ' || resp.status_code); dbms_output.put_line('HTTP response reason phrase: ' || resp.reason_phrase); -- Look for client-side error and report it. IF (resp.status_code >= 400) AND (resp.status_code <= 499) THEN -- Detect whether the page is password protected, and we didn't supply -- the right authorization. IF (resp.status_code = utl_http.HTTP_UNAUTHORIZED) THEN utl_http.get_authentication(resp, my_scheme, my_realm, my_proxy); IF (my_proxy) THEN dbms_output.put_line('Web proxy server is protected.'); dbms_output.put('Please supply the required ' || my_scheme || ' authentication username/password for realm ' || my_realm || ' for the proxy server.'); ELSE dbms_output.put_line('Web page ' || url || ' is protected.'); dbms_output.put('Please supplied the required ' || my_scheme || ' authentication username/password for realm ' || my_realm || ' for the Web page.'); END IF; ELSE dbms_output.put_line('Check the URL.'); END IF; utl_http.end_response(resp); RETURN; -- Look for server-side error and report it. ELSIF (resp.status_code >= 500) AND (resp.status_code <= 599) THEN dbms_output.put_line('Check if the Web site is up.'); utl_http.end_response(resp); RETURN; END IF; -- The HTTP header lines contain information about cookies, character sets, -- and other data that client and server can use to customize each session. FOR i IN 1..utl_http.get_header_count(resp) LOOP utl_http.get_header(resp, i, name, value); dbms_output.put_line(name || ': ' || value); END LOOP; -- Keep reading lines until no more are left and an exception is raised. LOOP utl_http.read_line(resp, value); dbms_output.put_line(value); END LOOP; EXCEPTION WHEN utl_http.end_of_body THEN utl_http.end_response(resp); END; END; / SET serveroutput ON -- The following URLs illustrate the use of this procedure, -- but these pages do not actually exist. To test, substitute -- URLs from your own Web server. exec show_url('http://www.oracle.com/no-such-page.html') exec show_url('http://www.oracle.com/protected-page.html') exec show_url('http://www.oracle.com/protected-page.html', 'scott', 'tiger')
これらのすべての機能のパッケージは、Oracle8i以上で提供されています。これらのパッケージは、Oracle HTTP Server(OHS)のmod_plsqlプラグインと組み合せて使用します。問合せの結果をHTML表にフォーマットしたり、イメージ・マップを作成することができます。また、HTTP Cookieの設定および取得を行ったり、CGI変数の値を確認することもできます。また、PL/SQLプログラムを使用して、その他の一般的なWeb操作を組み合せることもできます。
これらのパッケージのドキュメントは、データベース・ドキュメント・ライブラリの一部ではありません。ドキュメントの位置は、実行中の特定のアプリケーションによって異なります。これらのパッケージを使用するには、次に示すSQL*PlusのDESCRIBEコマンドを使用して、プロシージャ名およびパラメータを確認します。
DESCRIBE HTP; DESCRIBE HTF; DESCRIBE OWA_UTIL;
|
![]() Copyright © 2006 Oracle Corporation. All Rights Reserved. |
|