ASP 講義 8: ASP とデータベース (3)
著者:Eve Cole
更新時間:2009-05-30 19:55:00
前回の 2 回の講義では、ASP におけるデータベースの基本的な使い方について説明しました。今日は、非常に実践的なテクノロジをいくつか紹介します。
1. ページング技術 データを取得してブラウザに出力する方法を紹介しましたが、データ量が少ない場合は、このような単純な出力処理でも問題ありません。 , 一度にこれほど多くのデータをクライアントに出力するのは非現実的です。第 1 に、ページが上から下まで非常に長く続きます。第 2 に、クライアントの待ち時間が長すぎます。第 3 に、サーバーの負荷が高すぎます。したがって、ページングされた出力を取得することが非常に必要です。
要件: Northwind.mdb の「Product」テーブルのデータをブラウザに出力し、各ページに 10 項目を表示します。
wuf60.asp を例に挙げます。このコードはまだ少し難しいので、AdoAccess.asp については講義で説明されています。
注: このルーチンはいくつかの書籍から良い部分を組み込んでおり、ここに宣言します。
<%@ LANGUAGE="VBSCRIPT" %>
<!--#include file="AdoAccess.asp"-->
<!--#include file="adovbs.inc"-->
<%
Dim RecordPerPage、absPageNum、TotalPages、absRecordNum、rsTest、StrSQL
'absPageNum - 現在のページは何ページですか?
'TotalPages - 総ページ数
'absRecordNum - 現在のページのレコードのシリアル番号 (1 ~ 10 など)
RecordPerPage = 10 'ページごとに表示されるレコードの数
' 出力データの現在のページ番号を取得します
Request.ServerVariables("CONTENT_LENGTH") = 0 の場合
'フォームで送信されたデータが受信されなかった場合(ページの初回読み込み時など)は1ページ目から表示されます
absPageNum = 1
それ以外
'ボタンを押したときにページ番号を取得します
absPageNum = CInt(Request.Form("PressPageNum"))
'前のページを押すとページ番号が-1、次のページを押すとページ番号+1
If Request.Form("Submit") = "前のページ" then
absPageNum = absPageNum - 1
ElseIf Request.Form("Submit") = "次のページ" then
absPageNum = absPageNum + 1
終了の場合
終了の場合
'レコードセットオブジェクトの作成
Set rsTest = Server.CreateObject("ADODB.Recordset")
rsTest.CursorLocation = adUseClient 'この設定によりデータベースの負荷を軽減できます
rsTest.CursorType = adOpenStatic 'カーソルは前後に移動する必要があり、前方のみに設定することはできません
rsTest.CacheSize = RecordPerPage 'このオプションを設定するとパフォーマンスが向上します
StrSQL = "SELECT * FROM productOrder By productID"
rsTest.Open StrSQL、Cnn、、、adCmdText
rsTest.PageSize = RecordPerPage 'ページあたりのレコード数を設定します
そうでない場合(rsTest.EOF)
rsTest.AbsolutePage = absPageNum
終了の場合
TotalPages = rsTest.PageCount
%>
<% '次の部分は現在のページのデータをブラウザに出力します%>
<HTML><ボビー>
<tablecolspan=8 cellpadding=5 border=0>
<tr>
<td align=CENTER bgcolor="#800000" width="109"> <font style="ARIAL NARROW" color="#ffffff" size="2">単価</font></td>
<td align=CENTER width=459 bgcolor="#800000"> <font style="ARIAL NARROW" color="#ffffff" size="2">商品名</font></td>
</tr>
<% 'ループを使用して現在のページのデータを 10 個出力します
absRecordNum = 1 から rsTest.PageSize の場合
%>
<tr>
<td bgcolor="f7efde" align=CENTER> <font style="ARIAL NARROW" size="2"><%= rsTest("単価")%></font></td>
<td bgcolor="f7efde" align=CENTER> <font style="ARIAL NARROW" size="2"><%= rsTest("製品名")%></font></td>
</tr>
<%
rsTest.MoveNext
rsTest.EOF の場合、次に
Exit For ' レコードの終わりに達した場合、データの最後のページがいっぱいでない場合は終了します。
終了の場合
次
rsTest.Close : Cnn.Close
rsTest = なしを設定 : Cnn = なしを設定
%>
</テーブル>
<% '下部は「前ページ」「次ページ」の2つのボタンです %>
<フォームアクション = "<%= Request.ServerVariables("SCRIPT_NAME") %>" メソッド="Post">
<Input Type="Hidden" Name="PressPageNum" Value="<%= absPageNum%>">
<%
If absPageNum > 1 then '現在のページが最初のページでない場合は、前のページ ボタンを表示します%>
<入力タイプ="送信" 名前="送信" 値="前のページ">
<% 終了の場合
If absPageNum <> TotalPages then '現在のページが最後のページでない場合は、次のページ ボタンを表示します%>
<入力タイプ="送信" 名前="送信" 値="次のページ">
<% % の場合は終了>
</フォーム>
<P><Center> [ページ<font color="#CC0033"><%= absPageNum %></font>,
合計<font color="#CC0033"><%= TotalPages %></font> ページ] </Center></P>
</BODY></HTML>
分析します:
1. Recordset オブジェクトのいくつかの便利なプロパティ:
l rsTest.CursorLocation = adUseClient: この文は省略することもできますが、省略するとデータベースの負荷が軽減されます。
l rsTest.CacheSize = RecordPerPage: CacheSize 属性は、クライアントがデータベース サーバーから毎回取得するデータ量を決定するために使用されます。
l rsTest.PageSize: PageSize 属性は、各ページのレコード数を設定するために使用されます。
l rsTest.AbsolutePage: AbsolutePage プロパティは、Recordset オブジェクト内の現在のデータの絶対ページ数を設定します。
l rsTest.PageCount: PageCount プロパティは、レコード セット内の総ページ数を取得するために使用されます。
2.このサンプル フォームでは、隠しフィールド PressPageNum を使用して、ボタンがクリックされたときにページを渡します。
2. エラー処理 コードの実行中に、コード自体の問題やネットワークの切断など、さまざまな理由でエラーが発生する可能性があるため、プログラム内でエラーのキャプチャと処理を設定することが非常に必要です。 ASP では、Connection オブジェクトの Errors データ コレクションを通じて、コードの実行時に発生するエラーまたは警告情報を取得できます。使用方法は次のとおりです。
1. これを Connection オブジェクトで直接使用します。
エラー = Cnn.Errors を設定します
または
Cnn.エラー
2. Recordset オブジェクトまたは Command オブジェクトを確立した後、ActiveConnection プロパティを通じて Connection オブジェクトを使用します。
エラー = rsTest.ActiveConnection.Errors を設定します。
または
rsTest.ActiveConnection.Errors
あまりにも大雑把に聞こえるので、例を挙げてみましょう: wuf61.asp
<%@ LANGUAGE="VBSCRIPT" %>
<% 明示的なオプション %>
<!--#include file="adovbs.inc"-->
<%
応答.期限切れ = 0
'次の文は、スクリプトでエラーが発生しても、次の文の実行を継続することを保証します。
エラー時は次へ再開
薄暗い Cnn、rsTest、エラー、私
Set Cnn = Server.CreateObject("ADODB.Connection")
'CommandTimeout - データベースに接続するための最大待機時間、デフォルトは 15 秒です
Cnn.CommandTimeout = 5
'SQL Server を例にすると、次の 3 つの状況でエラーを検出できます。
'1 - 完全に正しい。2 - 初期データベースが設定されていない。3 - データベース名が間違っている。
Cnn.Open "プロバイダー=sqloledb; ユーザー ID=sa; パスワード=; 初期カタログ=pubs; データ ソース=ICBCZJP"
'Cnn.Open "プロバイダー = sqloledb; ユーザー ID = sa; パスワード =; 初期カタログ =; データ ソース = ICBCZJP"
'Cnn.Open "プロバイダー = sqloledb; ユーザー ID = sa; パスワード =; 初期カタログ = pvbs; データ ソース = ICBCZJP"
I = 0 ~ Cnn.Errors.Count - 1 の場合
'Source 属性はエラーのソースを示します
Response.Write "[ " & Cnn.Errors(I).Source & " ] "
'Description 属性はエラーの理由または説明を示します
Response.Write Cnn.Errors(I).Description & "<br>"
次
Cnn.Errors.Count > 0 の場合
Response.Write "接続中に発生しました" & Cnn.Errors.Count & " エラー" & "<br>"
終了の場合
Set rsTest = Server.CreateObject("ADODB.Recordset")
rsTest.Open "ジョブ"、Cnn、adOpenForwardOnly、adLockReadOnly、adCmdTable
rsTest.ActiveConnection.Errors.Count > 0 の場合
Set Session("Errs") = rsTest.ActiveConnection.Errors
Response.Redirect "ErrorHandle.asp"
終了の場合
Cnn.閉じる
rsTest = なしを設定 : Cnn = なしを設定
%>
ErrorHandle.asp コード:
<%
ディムI
I = 0 の場合、Session("Errs").Count - 1 へ
Response.Write "[ " & Session("Errs")(I).Source & " ] "
Response.Write Session("Errs")(I).Description & "<br>"
次
%>
分析します:
この場合、接続中にエラーが発生したか、接続は正しくても Recordset オブジェクトの使用中にエラーが発生した可能性があります。
さらに、次のコードでは、エラー コレクションをセッション オブジェクトに配置して、ページ間で呼び出せるようにしています (エラーが発生した場合は、エラー処理ページ ErrorHandle.asp に移動します)。
実際、Recordset オブジェクトを Session オブジェクトに割り当てて、ページ間でのレコードセットの呼び出しを実装することもできます。
3. トランザクションの使用の概念は非常にシンプルかつ重要です。その使用法を説明するために、まず次の状況を想定します。たとえば、電子商取引では、オンラインで通貨送金を行う場合、通貨から一定の金額を差し引く必要があります。アカウントの金額を変更し、その金額を別のアカウントに追加します。どちらの更新が失敗しても、アカウントの残高の不均衡が生じます (ここでは減額があるが、そこには増加がない、または、ここでは減額はないが、そこには増加がある) 。トランザクションを使用してこれらの変更を行う場合は、すべての変更を行うか、変更を行わないか (完全に修正するか完全にキャンセルするか) のみを選択できるようになります。
トランザクションは Connection オブジェクトに属しており、このオブジェクトにはトランザクション関連の 3 つのメソッドがあります。
l BeginTrans は新しいトランザクションを開始します。
l CommitTrans はすべての変更を保存し、現在のトランザクションを終了します。
l RollbackTrans は、現在のトランザクションで行われた変更をすべてキャンセルし、トランザクションを終了します。これは、多くの場合「ロールバック」と呼ばれます。
wuf62.asp の例も見てみましょう。
<%@ LANGUAGE="VBSCRIPT" %>
<% 明示的なオプション %>
<!--#include file="adovbs.inc"-->
<%
応答.期限切れ = 0
エラー時は次へ再開
DimCnn、StrSQL、rsTest
Set Cnn = Server.CreateObject("ADODB.Connection")
Cnn.Open "プロバイダー=sqloledb; ユーザー ID=sa; パスワード=; 初期カタログ=pubs; データ ソース=ICBCZJP"
'トランザクションを開始する
Cnn.BeginTrans
StrSQL = "ジョブの挿入(job_desc, min_lvl, max_lvl) 値('Finance',16,86)"
Cnn.StrSQL を実行する
「以下の最初の文は間違っていますが、2 番目の文は正しいです」
StrSQL = "job_err SET job_desc = 'トランザクション' を更新します。job_id = 14"
'StrSQL = "ジョブを更新 SET job_desc = 'トランザクション' Where job_id = 14"
Cnn.StrSQL を実行する
Cnn.Errors.Count > 0 の場合
Response.Write "エラーが発生しました。システムはトランザクション開始時の状態を復元します。新たな追加や変更は行われません。" & "<br>"
Cnn.RollbackTrans
それ以外
Response.Write "エラーはありません。データベースへの変更を保存し、新しいデータを追加し、データを変更します。" & "<br>"
Cnn.CommitTrans
終了の場合
Set rsTest = Cnn.Execute("ジョブ ID >=14 のジョブから * を選択")
rsTest.EOF ではない間
Response.Write rstest(0) & rstest(1) & rstest(2) & rstest(3) & "<br>"
rsTest.MoveNext
ウェン
'この例はテスト用ですので、データベースの元のデータを復元してください
Cnn.Execute "ジョブを更新 SET job_desc = 'Designer' Where job_id = 14"
Cnn.Execute 「job_id > 14 のジョブを削除」
Cnn.Close: Cnn = なしを設定します。
%>
この例では、挿入と更新が同時に発生するか、どちらも発生しません。データが追加されたにもかかわらずステートメント エラーにより変更が発生しないという状況は発生しません。データベースをプログラミングする場合、トランザクションを使用することは非常に良い習慣です。
4. 複数のレコードセットの処理 2 つのテーブルから同時にデータを取得する必要がある場合、1 つの SQL ステートメントで返されると、ネットワーク送信が削減され、操作効率が向上します。
wuf64.asp を例として、ループを使用してフィールド値を出力する方法も説明します (以前は、「rsTest(0) & rsTest(1) &...」などの愚かなメソッドを使用して出力していました)。フィールドが 2 つまたは 3 つしかない場合、この方法は明らかにより簡潔です)、現時点で理解できない場合は、より単純な wuf63.asp をダウンロードしてください。 。
<%@ LANGUAGE="VBSCRIPT" %>
<%
明示的なオプション
応答.期限切れ = 0
Dim Cnn、StrSQL、rsTest、I
Set Cnn = Server.CreateObject("ADODB.Connection")
Cnn.Open "プロバイダー=sqloledb; ユーザー ID=sa; パスワード=; 初期カタログ=pubs; データ ソース=ICBCZJP"
Set rsTest = Server.CreateObject("ADODB.Recordset")
'複数のレコードセットを取得します
StrSQL = "従業員から COUNT(*) AS '従業員数' を選択; ジョブから * を選択"
rsTest.Open StrSQL、Cnn '、、、、adCmdText
rsTest が何もない間は
Response.Write "<Table Border = 2><tr>"
'rsTest.Fields.Count - レコードセット内のフィールドの数
I = 0 から rsTest.Fields.Count - 1 まで
'rsTest(I).Name - I フィールドのフィールド名
Response.Write "<td>" & rsTest(I).Name & "</td>"
次
応答。「</tr>」を書き込みます。
rsTest.EOF ではない間
応答。「<tr>」を書き込みます。
'ループを使用して各フィールドの値を出力します
I = 0 から rsTest.Fields.Count - 1 まで
Response.Write "<td>" & rsTest(I) & "</td>"
次
応答。「</tr>」を書き込みます。
rsTest.MoveNext
ウェン
'次の Recordset オブジェクトを読み取ります
rsTest = rsTest.NextRecordset を設定します。
ウェン
Cnn.閉じる
rsTest = なしを設定します。Cnn = なしを設定します。
%>
注: SQL Server データベースは複数のレコード セットをサポートしますが、Access データベースはサポートしません。
5. できるだけ早く接続を閉じてリソースを解放します。
前の例では、接続は最後に閉じられましたが、実際には、以下の wuf65.asp によって提供されるメソッドに従って、接続をより早く閉じることができます。
<% @LANGUAGE = VBScript %>
<!--#include file="AdoAccess.asp"-->
<!--#include file="adovbs.inc"-->
<% ' wuf65.asp
ディム StrSQL、rsTest
StrSQL = "配送業者から * を選択"
Set rsTest =server.CreateObject("ADODB.Recordset")
'クライアント カーソルを使用する必要があります。そうしないと機能しません。
rsTest.CursorLocation = adUseClient
rsTest.Open StrSQL,Cnn,,,adCmdText
'Connection オブジェクトに対するレコードセットの依存関係を削除します
rsTest.ActiveConnection = なしを設定します
'できるだけ早く接続を閉じてください
Cnn.close: Cnn = なしを設定します。
rsTest.EOF を実行しないでください
Response.Write rsTest(0) & " " & rsTest(1) & " " & rsTest(2) & " " & "<BR>"
rsTest.MoveNext
ループ
rsTest = なしを設定します
%>