ヘッダーをスキップ
Oracle Databaseアドバンスト・アプリケーション開発者ガイド
11gリリース1(11.1)
E05687-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

11 PL/SQL Server Pagesの開発

この章では、Webページに動的コンテンツを含めることを可能にするPL/SQL Server Pages(PSP)の開発方法について説明します。

内容は次のとおりです。

PL/SQL Server Pagesの概要およびPL/SQL Server Pagesを使用する理由

PL/SQL Server Pages(PSP)は、WebページにSQL問合せの結果を含む動的コンテンツを含めるサーバー側スクリプトです。WebページをHTMLオーサリング・ツールで作成し、PL/SQLコード・ブロックを挿入できます。

例11-1に、simple.pspという名前の簡単なPL/SQL Server Pagesを示します。

例11-1 simple.psp

<%@ page language="PL/SQL" %>
<%@ page contentType="text/html" %>
<%@ plsql procedure="show_employees" %>
<%-- This example displays the last name and first name of every
     employee in the hr.employees table. --%>
<%!
  CURSOR emp_cursor IS
    SELECT last_name, first_name
      FROM hr.employees
        ORDER BY last_name;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>List of Employees</title>
</head>
<body TEXT="#000000" BGCOLOR="#FFFFFF">
<h1>List of Employees</h1>
<table width="40%" border="1">
<tr>
<th align="left">Last Name</th>
<th align="left">First Name</th>
</tr>
<%  FOR emp_record IN emp_cursor LOOP %>
  <tr>
  <td> <%= emp_record.last_name %> </td>
  <td> <%= emp_record.first_name %> </td>
  </tr>
<%  END LOOP; %>
</table>
</body>
</html>

loadpspコマンドライン・ユーティリティを使用すると、PL/SQL Server Pagesをコンパイルしてデータベースにロードできます。次のコマンドでは、simple.psphrスキーマにロードされ、show_employeesプロシージャが置換されます(すでに存在している場合)。

loadpsp -replace -user hr/password simple.psp

ブラウザ・ユーザーは、URLを介してshow_employeesプロシージャを実行できます。hr.employees表にある従業員の姓名を表示するHTMLページが、PL/SQLゲートウェイを介してブラウザに戻されます。

PL/SQL Server Pagesを介してコンテンツをデプロイする方法には、次のメリットがあります。

PL/SQL Server Pagesを開発してデプロイするための前提条件

PL/SQL Server Pagesを開発してデプロイするには、次の前提条件を満たす必要があります。

PL/SQL Server PagesおよびHTPパッケージ

次の方法で、ブラウザ・ユーザーがHTTPを介してPL/SQLユニットを実行できるようにすることができます。

そのため、Webアプリケーションの作成に使用する方法を選択する必要があります。これらの方法を選択する際のキーは、次のとおりです。

PL/SQL Server Pagesおよびその他のスクリプティング・ソリューション

スクリプティング・ソリューションは、クライアント側とサーバー側で使用できます。JavaScriptは、最も一般的なクライアント側スクリプト言語の1つです。PL/SQL Server Pagesは、JavaScriptを完全にサポートしています。PL/SQL Server Pages(PSP)を使用すると、すべてのタグが変更されずにブラウザに渡されるため、PL/SQL Server Pages(PSP)には、JavaScriptまたはその他のクライアント側のスクリプト・コードを含めることができます。

Java Server Pages(JSP)とActive Server Pages(ASP)は、最も一般的なサーバー側スクリプティング・ソリューションです。PL/SQL Server Pagesと対比すると次のようになります。


注意:

PSPに、サーバー側にあるその他のサーバー側スクリプト機能を混在させることはできません。多くの場合、対応するPL/SQL Server Pages機能を使用することによって、同じ結果を得ることができます。

PL/SQL Server Pagesの開発

PL/SQL Server Pagesを開発するには、既存のWebページから作業を開始する方法と、既存のストアド・サブプログラムから作業を開始する方法があります。どちらの方法でも、わずかな追加と変更のみで、データベース処理を実行し、結果を表示する動的なWebページを作成できます。

PL/SQL Server Pagesのファイルの拡張子は、.pspである必要があります。PL/SQL Server Pagesには、PL/SQL Server Pagesディレクティブ、宣言およびスクリプトレットとともにテキストまたはタグを配置することによって、選択した内容を含めることができます。PL/SQL Server Pagesには、次の書式を使用できます。

PL/SQL Server Pagesディレクティブと宣言の順序と位置は、通常は重要ではありません。重要になるのは、別のファイルが挿入される場合のみです。メンテナンスを簡単にするために、ディレクティブおよび宣言は、ともにファイルの最初の方に配置することをお薦めします。

表11-1PL/SQL Server Pagesの要素と使用方法の参照先を示します。各種PL/SQL Server Pages要素に使用される文字列を引用符で囲む方法については、「PSPスクリプトでの文字列の引用符およびエスケープ」を参照してください。

表11-1 PSPの要素

PSPの要素 名前 指定 参照先

<%@ page ... %>

ページ・ディレクティブ

PL/SQL Server Pagesの特性

基本的なPL/SQL Server Pages特性の指定


<%@ parameter ... %>

パラメータ・ディレクティブ

PSPストアド・プロシージャによって予測される各パラメータの名前、および(オプションで)型とデフォルト値

ユーザー入力の受入れ


<%@ plsql ... %>

プロシージャ・ディレクティブ

PSPファイルによって生成されたストアド・プロシージャの名前

PL/SQLストアド・プロシージャのネーミング


<%@ include ... %>

インクルード・ディレクティブ

PSPファイル内の特定のポイントに含めるファイルの名前

他のファイルのコンテンツの挿入


<%! ... %>

宣言ブロック

次のBEGIN/ENDブロック内のみでなく、ページ全体を通して参照できる、一連のPL/SQL変数の宣言

PSPスクリプトでのグローバル変数の宣言


<% ... %>

コード・ブロック

ストアド・プロシージャの実行時に実行される一連のPL/SQL文

PSPスクリプトでの実行可能文の指定


<%= ... %>

式ブロック

文字列、算術式、ファンクション・コールまたはこれらの組合せなど、単一のPL/SQL式

PSPスクリプトでの式の値の置換


<%-- ... --%>

コメント

PSPスクリプト内のコメント

PSPスクリプトへのコメントの挿入




注意:

すでに動的HTMLについて理解している場合は、「PL/SQL Server Pagesの例」に進んでください。

内容は次のとおりです。

基本的なPL/SQL Server Pages特性の指定

<%@ page ... %>ディレクティブを使用して、次のようなPL/SQL Server Pagesの特性を指定します。

  • 使用するスクリプト言語

  • 生成する情報のタイプ(MIMEタイプ)

  • 捕捉されなかったすべての例外を処理するために実行するコード。このコードは、わかりやすいメッセージを含むHTMLファイルの場合があり、.pspファイルに名前が変更されます。主なPSPファイルをコンパイルするloadpspコマンドにも同じファイル名を指定する必要があります。errorPageディレクティブおよびloadpspコマンドの両方に、../include/などのすべての関連パス名を含む同じ名前を正確に指定する必要があります。

次のコードは、pageディレクティブの構文を示しています(属性名contentTypeおよびerrorPageでは、大文字と小文字は区別されます)。

<%@ page
language='PL/SQL'
contentType='content_type_string'
charset='encoding'
errorPage='file.psp'
%>

内容は次のとおりです。

スクリプト言語の指定

ファイルをPL/SQL Server Pagesとして識別するには、ファイルのどこかに次のディレクティブを挿入します。

<%@ page language="PL/SQL" %>

このディレクティブは、他のスクリプティング環境との互換性を保つためのものです。例11-1に、言語ディレクティブを含む簡単なPL/SQL Server Pagesの例を示します。

クライアント・ブラウザへのデータの戻し方

オプション:

HTMLの戻し方

PL/SQL Server PagesのPL/SQL部分は、特別なデリミタで囲まれています。他のすべての内容は(空白を含めて)、ブラウザにそのまま渡されます。テキストまたはHTMLタグを表示するには、通常のWebページと同じように書き込みます。出力ファンクションを起動する必要はありません。たとえば、例11-1に示したPL/SQL Server Pagesは、例11-2に示すHTMLページを戻しますが、ここでは問い合せた従業員に関する表の行が含まれています。

例11-2 戻されるHTMLページのサンプル

<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>List of Employees</title>
</head>
<body TEXT="#000000" BGCOLOR="#FFFFFF">
<h1>List of Employees</h1>
<table width="40%" border="1">
<tr>
<th align="left">Last Name</th>
<th align="left">First Name</th>
</tr>

  <!-- result set of query of hr.employees inserted here -->

</table>
</body>
</html>

条件によって、出力を1行ずつ表示したり属性の値を変更する必要がある場合があります。例11-1から抜粋した次のコード部分のように、PSPデリミタ内に制御構造と置換変数を含めることができます。

<%  FOR emp_record IN emp_cursor LOOP %>
  <tr>
  <td> <%= emp_record.last_name %> </td>
  <td> <%= emp_record.first_name %> </td>
  </tr>
<%  END LOOP; %>
XML、テキストおよび他のドキュメント・タイプの戻し方

デフォルトでは、PL/SQLゲートウェイはファイルをHTMLドキュメントとして送信します。そのため、ブラウザはHTMLタグを解析します。ブラウザに、ドキュメントをXML、プレーン・テキスト(書式なし)またはその他のドキュメント・タイプとして解析させるには、次のディレクティブを含めます。

<%@ page contentType="MIMEtype" %>

属性名contentTypeは、大/小文字を区別します。text/htmltext/xmltext/plainimage/jpeg、またはブラウザやその他のクライアント・プログラムが認識できるその他のMIMEタイプを挿入します。MIMEタイプの中には、ユーザーがブラウザの設定を変更しないと認識されないものもあります。次に、Excelスプレッドシートに使用するディレクティブの例を示します。

<%@ page contentType="application/vnd.ms-excel" %>

通常、PL/SQL Server Pagesは、Webブラウザで表示されるように作成されています。また、JavaやPERLクライアントなど、HTTP要求を作成可能なプログラムによって取得または解析されることもあります。

別のキャラクタ・セットを含むページの戻し方

デフォルトでは、PL/SQLゲートウェイは、PL/SQLゲートウェイによって定義されたキャラクタ・セットを使用してファイルを送信します。ブラウザに表示するためにデータを別のキャラクタ・セットに変換するには、次のディレクティブを含めます。

<%@ page charset="encoding" %>

Shift_JISBig5UTF-8、またはクライアント・プログラムが認識できるその他のエンコーディングを指定します。

PL/SQLゲートウェイのデータベース・アクセス記述子(DAD)に設定するキャラクタ・セットも構成する必要があります。データが適切に表示されるようにするには、ユーザーが使用するブラウザで同じエンコーディングを選択する必要がある場合があります。たとえば、EUCエンコーディングを使用するデータベース・キャラクタ・セットが日本のデータベースに含まれていることがありますが、Webブラウザは、Shift_JISエンコーディングで表示するように構成されています。

スクリプト・エラーの処理

PL/SQL Server Pagesを書き込むときに、次のようなエラーが発生することがあります。

  • HTML構文エラー

    これらのエラーはブラウザで処理されます。loadpspユーティリティは、それらをチェックしません。

  • PL/SQL構文エラー

    loadpspユーティリティが停止し、行番号、列番号および簡単なメッセージを表示します。継続するには、エラーを修正する必要があります。

    ストアド・サブプログラムの以前のバージョンを構文エラーを含むスクリプトで置換しようとすると、そのストアド・サブプログラムは消去される場合があります。1つのデータベースをプロトタイプおよびデバック用に使用し、その後、最終的なストアド・サブプログラムを別の本番データベースにロードすることもできます。コマンドライン・フラグを使用すると、どのソース・コードを変更しなくてもデータベースを切り替えることができます。

  • ランタイム・エラー

    スクリプトの実行時に発生するデータベース・エラーを処理するには、PSPファイルにPL/SQL例外処理コードを含め、未処理の例外があれば、特別なPL/SQL Server Pagesに提示させます。ページ名は、<%@ page ... %>ディレクティブのerrorPage属性(名前は大/小文字を区別します)を使用して指定します。

    未処理の例外用のページは、拡張子.pspを持つPL/SQL Server Pagesです。エラー・サブプログラムは、どのパラメータも受け取りません。そのため、エラーの原因を判断するには、SQLCODEファンクションおよびSQLERRMファンクションを起動します。また、エラーが発生した場合は、スクリプトを使用しない標準HTMLページを表示することもできます。ただし、拡張子を.pspとし、ストアド・サブプログラムとしてデータベースにロードする必要があります。

    次の行は、エラー発生時に実行されるページとしてerrors.pspを指定しています。

    <%@ page language="PL/SQL" contentType="text/html" errorPage="errors.psp" %>
    

ユーザー入力の受入れ

PL/SQL Server Pagesへのパラメータ渡しを設定するには、次の構文のディレクティブを含めます。

<%@ plsql parameter="parameter_name" [type="PL/SQL_type"] [default="value"] %>

デフォルトのPL/SQL_typeVARCHAR2です。次のディレクティブは、パラメータp_employee_idのデータ型がNUMBERであることを指定しています。

<%@ plsql parameter="p_employee_id" type="NUMBER" %>

パラメータにデフォルト値を指定すると、そのパラメータはオプション・パラメータになります。デフォルト値はPL/SQL文に直接代入されるため、すべての文字列を引用符で囲む必要があります。また、NULLなどの特殊な値を使用できます。次のディレクティブは、パラメータp_last_nameのデフォルト値がNULLであることを指定しています。

<%@ plsql parameter="p_last_name" default="NULL" %>

ユーザー入力は、HTMLページを取得するURLにエンコードされます。URLを生成するには、ユーザー入力をHTMLリンクでハードコード化するか、またはHTML形式のアクションとしてページを起動します。これによって、ページは、PL/SQLストアド・サブプログラムへのパラメータとして入力を受け取ります。

例11-3例11-1と似ていますが、パラメータp_employee_idが使用される点が異なります。http://www.host.com/pls/proc_nameを起動して(proc_nameはプロシージャ名)プロシージャを実行できるようにPL/SQLゲートウェイが構成されている場合は、次のようにパラメータp_employee_id200を渡すことができます。

http://www.example.com/pls/show_employees?p_employee_id=200

例11-3 simplewithuserinput.psp

<%@ page language="PL/SQL" %>
<%@ page contentType="text/html" %>
<%@ plsql parameter="p_employee_id" default="null" type="NUMBER" %>
<%@ plsql procedure="show_employees" %>
<%-- This example displays the last name and first name of every
     employee in the hr.employees table. --%>
<%!
  CURSOR emp_cursor IS
  SELECT last_name, first_name
  FROM hr.employees
  WHERE employee_id = p_employee_id
  ORDER BY last_name;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>List of Employees</title>
</head>
<body TEXT="#000000" BGCOLOR="#FFFFFF">
<h1>List of Employees</h1>
<table width="40%" border="1">
<tr>
<th align="left">Last Name</th>
<th align="left">First Name</th>
</tr>
<%  FOR emp_record IN emp_cursor LOOP %>
  <tr>
  <td> <%= emp_record.last_name %> </td>
  <td> <%= emp_record.first_name %> </td>
  </tr>
<%  END LOOP; %>
</table>
</body>
</html>

PL/SQLストアド・プロシージャのネーミング

トップレベルの各PL/SQL Server Pagesは、サーバー内の1つのストアド・プロシージャと対応しています。loadpspを使用してページをロードすると、このユーティリティによりPL/SQLストアド・プロシージャが作成されます。サーバー・ページがname.pspである場合、デフォルトのプロシージャ名はnameです。たとえば、サーバー・ページがhello_world.pspの場合、デフォルトのプロシージャ名はhello_worldです。

プロシージャ名を指定するには、次のディレクティブを使用します。procnameはプロシージャの名前です。

<%@ plsql procedure="procname" %>

例11-1では、次のディレクティブによりストアド・プロシージャにshow_employeesという名前が与えられます。

<%@ plsql procedure="show_employees" %>

これはPSPスクリプト名ではなく、URLに挿入するプロシージャの名前です。

他のファイルのコンテンツの挿入

挿入メカニズムを設定することによって、通常、静的HTMLコンテンツまたはより多くのPL/SQLスクリプト・コードのいずれかを含む別のファイルのコンテンツを含めることができます。filenameを挿入するファイルの名前で置き換えて、他のファイルのコンテンツを表示する位置に次のディレクティブを挿入します。

<%@ include file="filename" %>

インクルード・ファイルには、.psp以外の拡張子を付ける必要があります。includeディレクティブおよびloadpspコマンドの両方に、../include/などのすべての関連パス名を含む同じ名前を正確に指定する必要があります。

ファイルは、ストアド・プロシージャをデータベースにロードするときに処理されるため、置換は、ページの提示ごとではなく、1回のみ実行されます。したがって、ページがデータベースにロードされた後に、インクルード・ファイルに変更が発生した場合、変更内容はプロシージャの実行時に表示されません。

挿入機能を使用してナビゲーション・バナー、フッター、目次などのコード・ライブラリに含めると、複数のファイルに挿入できます。また、この機能をマクロ機能として使用し、スクリプト・コードの同じセクションを1つのページの複数の位置に含めることもできます。次の例では、HTMLフッターを含めています。

<%@ include file="footer.htm" %>

インクルード・ファイルを使用する場合:

  • インクルード・ファイルには、どのような名前および拡張子でも使用できます。たとえば、products.txtというファイルを含めることができます。

  • インクルード・ファイルにPL/SQLスクリプト・コードが含まれている場合、プロシージャ名やキャラクタ・セットなどを識別するための独自のディレクティブは必要ありません。

  • loadpspユーティリティにファイル名を指定するときは、すべてのインクルード・ファイルの名前も含める必要があります。インクルード・ファイルの名前は、すべての.pspファイル名より前に指定してください。

PSPスクリプトでのグローバル変数の宣言

<%! ... %>ディレクティブを使用して、次のBEGIN/ENDブロック内のみでなく、ページ全体を通して参照できる、一連のPL/SQL変数を定義できます。通常、この要素は複数行にまたがっており、最後にセミコロンが付いた個々のPL/SQL変数宣言を持ちます。このディレクティブの構文は次のとおりです。

<%! PL/SQL declaration;
    [ PL/SQL declaration; ] ... %>

標準的なPL/SQL構文は、ブロック内で使用できます。デリミタは略記として機能するため、DECLAREキーワードを省略できます。すべての宣言は、ファイル内のその後のコードに使用できます。例11-1には、次のカーソル宣言が含まれています。

<%!
  CURSOR emp_cursor IS
  SELECT last_name, first_name
  FROM hr.employees
  ORDER BY last_name;
%>

複数の宣言ブロックを内部的に指定できます。それらはすべて、PSPファイルがストアド・プロシージャとして作成されたときに単一ブロックにマージされます。

「PSPスクリプトでの実行可能文の指定」で説明する<% ... %>デリミタ内に明示的なDECLAREブロックを使用することもできます。これらの宣言は、後続のBEGIN/ENDブロックのみが参照できます。


注意:

すべてのディレクティブおよび宣言をPL/SQL Server Pagesの最初の方にまとめて配置すると、メンテナンスがより簡単になります。

PSPスクリプトでの実行可能文の指定

<% ... %>コード・ブロック・ディレクティブを使用して、ストアド・プロシージャの実行時に一連のPL/SQL文を実行できます。次のコードは、実行可能文の構文を示しています。

<% PL/SQL statement;
   [ PL/SQL statement; ] ... %>

通常、この要素は複数行にまたがっており、最後にセミコロンが付いた個々のPL/SQL変数宣言を持ちます。この文は、次の例に示すように、OWA_UTIL.TABLEPRINTプロシージャを起動する完全なブロックを含むこともできます。

<% OWA_UTIL.TABLEPRINT(CTABLE => 'hr.employees', CATTRIBUTES => 'border=2',
   CCOLUMNS => 'last_name,first_name', CCLAUSES => 'WHERE employee_id > 100'); %>

また、この文はIF/THEN/ELSEまたはBEGIN/ENDブロックの大カッコで囲まれた部分になることもできます。コード・ブロックが複数のディレクティブに分割されると、HTMLまたはその他のディレクティブを途中に置くことができます。これによって、これら複数のスクリプトレットは、ストアド・プロシージャが実行されたときに、条件付きで実行されます。例11-11から抜粋した次のコードは、この方法を示しています。

  <% FOR ITEM IN (SELECT product_name, list_price, catalog_url
                  FROM product_information
                  WHERE list_price IS NOT NULL
                  ORDER BY list_price DESC) LOOP
     IF item.list_price > p_minprice THEN
        v_color := '#CCCCFF';
     ELSE
        v_color := '#CCCCCC';
     END IF;
  %>
  <TR BGCOLOR="<%= v_color %>">
    <TD><A HREF="<%= item.catalog_url %>"><%= item.product_name %></A></TD>
    <TD><BIG><%= item.list_price %></BIG></TD>
  </TR>
  <% END LOOP; %>

標準的なすべてのPL/SQL構文は、ブロック内で使用できます。デリミタは略記として機能するため、DECLAREキーワードを省略できます。すべての宣言は、ファイル内のその後のコードに使用できます。


注意:

異なるPL/SQL Server Pages間でプロシージャ、定数および型を共有するには、プレーンなPL/SQLソース・ファイルを使用して、それらをデータベース内のパッケージにコンパイルします。PSPスクリプトからパッケージ・プロシージャ、定数および型を参照できますが、PSPスクリプトで生成できるのは、パッケージではなくスタンドアロン・プロシージャのみです。

PSPスクリプトでの式の値の置換

式ディレクティブは、文字列、算術式、ファンクション・コールまたはこれらの組合せなど、単一のPL/SQL式を出力します。結果は、ストアド・プロシージャによって生成されたHTMLページ内の該当部分で文字列に置き換えられます。式の結果は、文字列値であるか、文字列にキャストできる値である必要があります。DATEなど、暗黙的にキャストできない型の場合、値をPL/SQLのTO_CHARファンクションに渡します。

式ディレクティブの構文は、次のとおりです。expressionプレースホルダを必要な式で置き換えてください。

<%= expression %>

PL/SQL式の最後にセミコロンを付ける必要はありません。

例11-1には、次のように変数値を1つのカーソル行に出力するディレクティブが含まれています。

<%= emp_record.last_name %>

この例を、次の例に示す同等のhtp.printコールと比較してください(特に、文の終わりのセミコロンに注意してください)。

<% HTP.PRN (emp_record.last_name); %>

<%= ... %>デリミタ内の内容は、HTP.PRNファンクションによって処理されます。ここでは、先行または後続の空白はすべて切り捨てられ、リテラル文字列を引用符で囲むことが要求されます。

PL/SQLの場合と同様、二重パイプ記号(||)を使用すると連結できます。次のディレクティブに連結例を示します。

<%= 'The employee last name is ' || emp_record.last_name %>

PSPスクリプトでの文字列の引用符およびエスケープ

PSP属性では、データのデリミタとして二重引用符が使用されます。PSP属性に指定された値がPL/SQL処理に使用された場合、それらはPSPファイルに指定されたとおりに渡されます。そのため、PL/SQLが一重引用符付き文字列を要求する場合、その文字列を一重引用符で囲み、すべてを二重引用符で囲んで指定する必要があります。

たとえば、PL/SQLプロシージャで変数のデフォルト値として文字列Babe Ruthを使用するとします。この文字列はPL/SQLで使用されるため、'Babe Ruth'のように一重引用符で囲む必要があります。このように一重引用符で囲んだ文字列をPSPディレクティブのdefault属性に指定する場合は、次の例に示すように二重引用符で囲む必要があります。

<%@ plsql parameter="in_players" default="'Babe Ruth'" %>

一重引用符の中に一重引用符付きの文字列をネストすることもできます。この場合、シーケンス\'を指定してネストされた一重引用符をエスケープする必要があります。次に例を示します。

<%@ plsql parameter="in_players" default="'Walter \'Big Train\' Johnson'" %>

ほとんどの文字および文字列は、PSPローダーで変更しなくてもPSPファイルに含めることができます。シーケンス%>を含めるには、エスケープ・シーケンス%\>を指定します。シーケンス<%を含めるには、エスケープ・シーケンス<\%を指定します。次に例を示します。

<%= 'The %\> sequence is used in scripting language: ' || lang_name %>
<%= 'The <\% sequence is used in scripting language: ' || lang_name %>

PSPスクリプトへのコメントの挿入

PL/SQL Server PagesのHTML部分にコメントを挿入する場合、PSPソース・コードが簡単に読めるように次の構文を使用します。

<%-- PSP comment text --%>

前述した書式のコメントはPSPからのHTML出力には表示されず、USER_OBJECTS内のPL/SQLソース・コードを問い合せても表示されません。

HTML出力およびUSER_OBJECTSソースに表示されるコメントを作成するには、HTMLにコメントを挿入して、次のような通常のHTMLコメント構文を使用します。

<!-- HTML comment text -->

PSP内でPL/SQLブロックの中にコメントを挿入し、HTML出力では参照できないがUSER_OBJECTS内では参照できるようにするには、次の例に示すように通常のPL/SQLコメント構文を使用します。

-- Comment in PL/SQL code

例11-4に、3タイプのコメントを含むPSPファイルの断片を示します。

例11-4 PSPファイル内のサンプル・コメント

<p>Today we introduce our new model XP-10.
<%--
  This is the project with code name "Secret Project".
  Users viewing the HTML page will not see this PSP script comment.
  The comment is not visible in the USER_OBJECTS source code.
--%>
<!--
  Some pictures of the XP-10.
  Users viewing the HTML page source will see this comment.
  The comment is also visible in the USER_OBJECTS source code.
-->
<%
FOR image_file IN (SELECT pathname, width, height, description
                   FROM image_library WHERE model_num = 'XP-10')
-- Comments interspersed with PL/SQL statements.
-- Users viewing the HTML page source will not see these PL/SQL comments.
-- These comments are visible in the USER_OBJECTS source code.
LOOP
%>
<img src="<%= image_file.pathname %>" width=<% image_file.width %>
height=<% image_file.height %> alt="<% image_file.description %>">
<br>
<% END LOOP; %>

データベースへのPL/SQL Server Pagesのロード

$ORACLE_HOME/binにあるloadpspユーティリティを使用して、1つ以上のPSPファイルをストアド・プロシージャとしてデータベースにロードします。各.pspファイルは1つのストアド・プロシージャと対応します。開発サイクルを短くするために、ページのコンパイルおよびロードは1手順で行われます。loadpspユーティリティの構文は、次のとおりです。

loadpsp [-replace] -user username/password[@connect_string]
  [includefile...] [errorfile] pspfile...

CREATE OR REPLACE構文でプロシージャを作成するには、-replaceフラグを使用します。

PSPファイルのロード時に、ローダーにより次のアクションが実行されます。

  1. 指定したユーザー名、パスワードおよびネット・サービス名を使用してデータベースにログインします。

  2. ユーザー・スキーマにストアド・プロシージャを作成します。

PL/SQL Server Pages名の前に、すべてのインクルード・ファイルの名前を含めます。さらに、pageディレクティブのerrorPage属性に指定されたファイルの名前も含めます。loadpspコマンドライン上のこれらのファイル名は、../include/などの関連パス名も含めて、PL/SQL Server Pagesのincludeディレクティブおよびpageディレクティブに指定された名前と完全に一致する必要があります。例11-5に、PSPロード・コマンドの例を示します。

例11-5 PL/SQL Server Pagesのロード

loadpsp -replace -user joe/abc123@/db3 banner.inc error.psp display_order.psp

例11-5の内容は次のとおりです。

PL/SQL Server Pagesソース・コードの問合せ

loadpspによって生成されるコードは、ソース・ファイル内のコードとは異なります。WebページのHTMLタグを生成するHTPパッケージへのコールを含んでいます。

PSPファイルをロードした後、静的データ・ディクショナリ・ビュー*_SOURCEに対して問合せを行うことにより、生成されたソース・コードを表示できます。たとえば、次のコマンドを使用して例11-1のスクリプトをロードするとします。

loadpsp -replace -user hr/password simple.psp

データベースにユーザーhrとしてログインすると、例11-6のようにSQL*Plusで問合せを実行してPSPのソース・コードを表示できます。

例11-6 PL/SQL Server Pageソース・コードの問合せ

SQL> SELECT TEXT
  2    FROM USER_SOURCE
  3      WHERE NAME = 'SHOW_EMPLOYEES'
  4        ORDER BY LINE;

PROCEDURE show_employees  AS

  CURSOR emp_cursor IS
  SELECT last_name, first_name
  FROM hr.employees
  ORDER BY last_name;

 BEGIN NULL;
owa_util.mime_header('text/html'); htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('
');
htp.prn('
<html>
<head>
<meta http-equiv="Content-Type" content="text/html">
<title>List of Employees</title>
</head>
<body TEXT="#000000" BGCOLOR="#FFFFFF">
<h1>List of Employees</h1>
<table width="40%" border="1">
<tr>
<th align="left">Last Name</th>
<th align="left">First Name</th>
</tr>
');
  FOR emp_record IN emp_cursor LOOP
htp.prn('
  <tr>
  <td> ');
htp.prn( emp_record.last_name );
htp.prn(' </td>
  <td> ');
htp.prn( emp_record.first_name );
htp.prn(' </td>
  </tr>
');
  END LOOP;
htp.prn('
</table>
</body>
</html>
');
 END;

50 rows selected.

SQL>

URLを介したPL/SQL Server Pagesの実行

PL/SQL Server Pagesが一度ストアド・プロシージャに変換されると、Webブラウザまたは他のインターネット関連クライアント・プログラムを使用してHTTP URLを取得することによって、そのプロシージャを実行できます。URLの仮想パスは、PL/SQLゲートウェイが構成された方法によって異なります。

ストアド・プロシージャへのパラメータは、HTTPプロトコルのPOSTメソッドまたはGETメソッドのいずれかを使用して渡されます。POSTメソッドの場合、パラメータはHTMLフォームから直接渡され、URLには表示されません。GETメソッドの場合、パラメータはURLの問合せ文字列で名前/値ペアとして渡されます。URLの問合せ文字列は、エンコード形式のほとんどの英数字以外の文字(たとえば、空白は%20)で、&文字で区切られています。PSPページをHTMLフォームから起動するには、GETメソッドを使用します。また、特定のパラメータ・セットを持つストアド・プロシージャを起動するには、ハードコード化されたHTMLリンクを使用します。

METHOD=GETを使用する場合、URLの構文は次のようになります。

http://sitename/schemaname/procname?parmname1=value1&parmname2=value2

たとえば、次のURLにはp_lnameおよびp_fnameパラメータが含まれています。

http://www.example.com/pls/show_employees?p_lname=Ashdown&p_fname=Lance

METHOD=POSTを使用した場合、パラメータはURL構文に表示されません。

http://sitename/schemaname/procname

たとえば、次のURLではプロシージャ名は指定されていますが、パラメータは渡されません。

http://www.example.com/pls/show_employees

METHOD=GET形式は、デバッグに有効です。また、ページの閲覧者がブックマークを使用して再度ページを開く際、同じパラメータを渡すことができます。

METHOD=POST形式は、さらに大きいパラメータ・データを扱えます。また、URLに表示できない機密情報を渡す場合に適しています。(URLは、ブラウザの履歴リスト、および次のアクセス・ページに渡されるHTTPヘッダーの中に残ります。)この方法で起動されたページにブックマークを付けるのは、効果的ではありません。

PL/SQL Server Pagesの例

この項では、非常に単純なPL/SQL Server Pagesから始め、徐々に複雑なバージョンを作成していく方法を説明します。

各手順を行いながら、「データベースへのPL/SQL Server Pagesのロード」および「URLを介したPL/SQL Server Pagesの実行」の指示に従って例をテストしてください。

内容は次のとおりです。

PL/SQL Server Pagesの例のための設定

各例では、後述のように、OEスキーマ内のPRODUCT_INFORMATION表を使用します。

SQL> DESCRIBE PRODUCT_INFORMATION;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 PRODUCT_ID                                NOT NULL NUMBER(6)
 PRODUCT_NAME                                       VARCHAR2(50)
 PRODUCT_DESCRIPTION                                VARCHAR2(2000)
 CATEGORY_ID                                        NUMBER(2)
 WEIGHT_CLASS                                       NUMBER(1)
 WARRANTY_PERIOD                                    INTERVAL YEAR(2) TO MONTH
 SUPPLIER_ID                                        NUMBER(6)
 PRODUCT_STATUS                                     VARCHAR2(20)
 LIST_PRICE                                         NUMBER(8,2)
 MIN_PRICE                                          NUMBER(8,2)
 CATALOG_URL                                        VARCHAR2(50)

SQL>

各例の想定は次のとおりです。

例11-7のようにOWA_UTIL.TABLEPRINTをコールして、デバッグのためにSQL表の内容全体を表示できます。後の例では、表示をさらに制御する他の方法を示します。

例11-7 show_prod_simple.psp

<%@ plsql procedure="show_prod_simple" %>
<HTML>
<HEAD><TITLE>Show Contents of product_information (Complete Dump)</TITLE></HEAD>
<BODY>
<%
DECLARE
  dummy BOOLEAN;
BEGIN
  dummy := OWA_UTIL.TABLEPRINT('oe.product_information','border');
END;
%>
</BODY>
</HTML>

次のように、例11-7のPSPをコマンドラインでロードします。

loadpsp -replace -user oe/password show_prod_simple.psp

次のURLを介してPSPにアクセスします。

http://www.example.com/pls/show_prod_simple

ループを使用したサンプル表の出力

例11-7では、product_information表の項目をループし、SELECT文を調整して、行または列のサブセットのみを取得します。この例では、一致していない表タグまたはクローズしていない表タグによる問題を回避するために、非常に単純な一連のリスト品目を例として示します。

例11-8 show_catalog_raw.psp

<%@ plsql procedure="show_prod_raw" %>
<HTML>
<HEAD><TITLE>Show Products (Raw Form)</TITLE></HEAD>
<BODY>
<UL>
<% FOR item IN (SELECT product_name, list_price, catalog_url
                FROM product_information
                WHERE list_price IS NOT NULL
                ORDER BY list_price DESC) LOOP %>
<LI>
Item = <%= item.product_name %><BR>
Price = <%= item.list_price %><BR>
URL = <%= item.catalog_url %><BR>
<% END LOOP; %>
</UL>
</BODY>
</HTML>

例11-9に、より洗練された例11-8のバリエーションを示します。この例では、表示を改善するためにHTMLに書式が追加されています。

例11-9 show_catalog_pretty.psp

<%@ plsql procedure="show_prod_pretty" %>
<HTML>
<HEAD><TITLE>Show Products (Better Form)</TITLE></HEAD>
<BODY>
<UL>
<% FOR item IN (SELECT product_name, list_price, catalog_url
                FROM product_information
                WHERE list_price IS NOT NULL
                ORDER BY list_price DESC) LOOP %>
<LI>
Item = <A HREF=<%= item.catalog_url %>><%= item.product_name %></A><BR>
Price = <BIG><%= item.list_price %></BIG><BR>
<% END LOOP; %>
</UL>
</BODY>
</HTML>

ユーザー選択の許可

例11-7例11-8および例11-9では、PRODUCT_INFORMATION表が更新されないかぎりHTMLページは変わりません。例11-10では次の処理が行われます。

  • HTMLページに最低価格を入力できるようにし、それよりも高価な品目のみを表示するようにします。(顧客の購買基準は様々です。)

  • デフォルトの最低価格を100(単位は該当通貨)に設定します。

例11-10 show_product_partial.psp

<%@ plsql procedure="show_product_partial" %>
<%@ plsql parameter="p_minprice" default="100" %>
<HTML>
<HEAD><TITLE>Show Items Greater Than Specified Price</TITLE></HEAD>
<BODY>
<P>This report shows the items whose price is greater than <%= p_minprice %>.
<UL>
<% FOR ITEM IN (SELECT product_name, list_price, catalog_url
                FROM product_information
                WHERE list_price > p_minprice
                ORDER BY list_price DESC)
   LOOP %>
<LI>
Item = <A HREF="<%= item.catalog_url %>"><%= item.product_name %></A><BR>
Price = <BIG><%= item.list_price %></BIG><BR>
<% END LOOP; %>
</UL>
</BODY>
</HTML>

例11-10をデータベースにロードした後、URLを介してshow_product_partialプロシージャにパラメータを渡すことができます。次の例では、最低価格250を指定しています。

http://www.example.com/pls/show_product_partial?p_minprice=250

結果のフィルタリングは、検索結果など、選択肢がユーザーにとって多すぎる可能性があるアプリケーションには有用です。ただし、小売りの場合は、顧客が他の品目も選択できるように、例11-11に示す別の方法を使用する必要があります。

  • WHERE句を使用して結果をフィルタするかわりに、すべての結果セットを取得し、戻された各行に対して別々のアクションを実行します。

  • HTMLを変更して、基準に合う出力のみをハイライト表示させます。例11-11では、HTML表の行にバックグラウンド・カラーを使用します。最も重要な行が目立つようにするために、特別なアイコンを挿入したり、フォント・サイズを大きくすることもできます。

  • 結果をHTML表に表示します。

例11-11 show_product_highlighed.psp

<%@ plsql procedure="show_product_highlighted" %>
<%@ plsql parameter="p_minprice" default="100" %>
<%! v_color VARCHAR2(7); %>

<HTML>
<HEAD><TITLE>Show Items Greater Than Specified Price</TITLE></HEAD>
<BODY>
<P>This report shows all items, highlighting those whose price is
 greater than <%= p_minprice %>.
<P>
<TABLE BORDER>
  <TR>
    <TH>Product</TH>
    <TH>Price</TH>
  </TR>
  <% FOR ITEM IN (SELECT product_name, list_price, catalog_url
                  FROM product_information
                  WHERE list_price IS NOT NULL
                  ORDER BY list_price DESC) LOOP
     IF item.list_price > p_minprice THEN
        v_color := '#CCCCFF';
     ELSE
        v_color := '#CCCCCC';
     END IF;
  %>
  <TR BGCOLOR="<%= v_color %>">
    <TD><A HREF="<%= item.catalog_url %>"><%= item.product_name %></A></TD>
    <TD><BIG><%= item.list_price %></BIG></TD>
  </TR>
  <% END LOOP; %>
</TABLE>
</BODY>
</HTML>

HTMLフォームを使用したPL/SQL Server Pagesの起動

例11-12に、ユーザーが価格を入力できるHTMLフォームの要点を示します。このフォームは、例11-10に示したshow_product_partialストアド・プロシージャを起動し、入力された値をp_minpriceパラメータとして渡します。

このフォームのACTION=属性で、ストアド・プロシージャのURL全体をコード化することを回避するには、そのストアド・プロシージャが起動するPSPファイルと同じディレクトリに置かれるように、このフォームをPSPファイルとして作成します。このHTMLファイルにはPL/SQLコードが含まれていませんが、これに.psp拡張子を付け、ストアド・プロシージャとしてデータベースにロードできます。URLを介してproduct_formストアド・プロシージャが実行されたとき、HTMLはファイルに表示されるとおりに表示されます。

例11-12 product_form.psp

<HTML>
<BODY>
<FORM method="POST" action="show_product_partial">
  <P>Enter the minimum price you want to pay:
  <INPUT type="text" name="p_minprice">
  <INPUT type="submit" value="Submit">
</FORM>
</BODY>
</HTML>

PSPファイルへのJavaScriptの挿入

JavaScriptなどの動的コンテンツを含むような、複雑なHTMLファイルを生成するには、ソース・コードをPL/SQL Server Pagesとして実装することによって単純化します。この方法では、ネストされた引用符、エスケープ文字、連結リテラルや変数および埋込みコンテンツのインデントを考慮する必要がなくなります。

例11-13例11-10の別バージョンを示します。このバージョンでは、ユーザーがマウスを製品URLに置くと、JavaScriptを使用してブラウザのステータス・バーに注文のステータスが表示されます。

例11-13 show_product_javascript.psp

<%@ plsql procedure="show_product_javascript" %>
<%@ plsql parameter="p_minprice" default="100" %>
<HTML>
<HEAD>
  <TITLE>Show Items Greater Than Specified Price</TITLE>

<SCRIPT language="JavaScript">
<!--hide

var text=" ";

function overlink (text)
{
  window.status=text;
}
function offlink (text)
{
  window.status=text;
}

//-->
</SCRIPT>

</HEAD>
<BODY>
<P>This report shows the items whose price is greater than <%= p_minprice %>.
<P>
<UL>
<% FOR ITEM IN (SELECT product_name, list_price, catalog_url, product_status
                FROM product_information
                WHERE list_price > p_minprice
                ORDER BY list_price DESC)
   LOOP %>
<LI>
Item =
  <A HREF="<%= item.catalog_url %>"
  onMouseover="overlink('PRODUCT STATUS: <%= item.product_status %>');return true"
  onMouseout="offlink(' ');return true">
    <%= item.product_name %>
  </A>
<BR>
Price = <BIG><%= item.list_price %></BIG><BR>
<% END LOOP; %>
</UL>
</BODY>
</HTML>

PL/SQL Server Pagesのデバッグ

PL/SQL Server Pagesに取り組み始めた際、および最初の単純なページからより複雑なページに進む過程で、問題が発生した場合は、次のガイドラインに従ってください。

PL/SQL Server Pagesの商品化

PSPアプリケーションを商品化する前に、有用性やダウンロード速度などの問題も考慮する必要があります。