データベース千夜一夜第14回

プログラミングとSQL(2)
~レコードの削除処理
長谷川裕行
有限会社 手國堂

サンプルアプリケーションの作成

上記の仕様に基づいて、実際にアプリケーションを作ってみます。あくまでサンプルなので、細部のデザインは簡潔にしています。データの受け渡しをSQLの実行部分に注目してください。


- グローバル変数で情報を受け渡す -

検索処理と削除処理を別プロシージャとするため、2つのプロシージャ間で処理対象のレコードを特定する情報を受け渡しするグローバル変数を用意します。

  Public Class Form1
   Inherits System.Windows.Forms.Form
   Dim strTargetId As String ← 削除対象の商品IDを保存
   Dim strTargetName As String ← 削除対象の商品名を保存

本来は商品IDを保存するだけでよいのですが、ここではユーザーに商品名まで示して確認を求めるため、商品名もグローバル変数に保存しておきます。


- 商品検索処理 -

商品のレコードを検索する部分は、前回のサンプルと同じ“btnSearch_Click”プロシージャが担当します。表示するフィールドが異なる以外、基本部分は前回とまったく同じです。

Private Sub btnSearch_Click _
(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnSearch.Click

Dim strSql As String

↓検索用の接続文字列を設定
strSql = _
"SELECT 商品_dmy.商品ID, 商品_dmy.品名, 在庫_mr.在庫 " & _
"FROM 商品_dmy INNER JOIN 在庫_mr ON 商品_dmy.商品ID = 在庫_mr.商品ID " & _
"WHERE 商品_dmy.商品ID = "

↓テキストボックスの未入力チェック
If Me.txtItemId.Text = "" Then
   MessageBox.Show("商品IDを入力してください。", _
    "入力エラー", MessageBoxButtons.OK)
Else ← パラメータを付け足して検索を実行
   strSql = strSql & txtItemId.Text
   Search(strSql)
End If
End Sub


- 検索の下請け処理 -

実際の検索処理は、下請けプロシージャ“Search”に委ねます。異なるのは、検索されたレコードの「商品ID」と「品名」フィールドの値をグローバル変数に代入する処理です(★マークの箇所)。

Private Sub Search(ByVal strSql As String)
 Dim objConnect As New SqlConnection
 Dim objCommand As New SqlCommand
 Dim objDataReader As SqlDataReader
    ↑検索処理なのでDataReaderオブジェクトを用いる
Try
  objConnect.ConnectionString = _
  "Persist Security Info=False;Integrated Security=SSPI;database=db1001ya;server=localhost"
  objCommand.Connection = objConnect
  objConnect.Open()

  objCommand.CommandText = strSql

  objDataReader = objCommand.ExecuteReader(CommandBehavior.SingleRow)
  If objDataReader.Read() Then ' 検索成功
   lblItemName.Text = objDataReader("品名")
   lblNumStock.Text = objDataReader("在庫")
   ↓削除対象の商品IDと商品名をグローバル変数保存
   strTargetId = txtItemId.Text -------- ★
   strTargetName = lblItemName.Text ---- ★
  Else
   MessageBox.Show( _
   "該当する商品が見つかりません。", "検索エラー", MessageBoxButtons.OK)
   strTargetId = ""
   strTargetName = ""
   Exit Sub
  End If

  Catch objExcept As Exception
  MessageBox.Show(objExcept.ToString, "DBエラー", MessageBoxButtons.OK)

  Finally
   If Not objDataReader Is Nothing Then
    objDataReader.Close()
   End If
   If Not objConnect Is Nothing Then
    objConnect.Close()
   End If
End Try
End Sub


- レコードの削除処理 -

削除を行うプロシージャは“btnDelete_Click”です。ここで、検索処理で確定された削除対象レコードを示す「商品ID」(strTargetIdの値)を使ってDELETE命令を実行するSQLを生成し、ExecuteNonQueryメソッドを実行してレコードを削除します。

★マークの行

 If objCommand.ExecuteNonQuery >= 1 Then

が、レコード削除のSQLを実行してその結果を判断している箇所です。ExecuteNonQueryの戻り値が-1または0なら削除は行われなかったと見なし、それ以外の時は削除成功と判断しています。

Private Sub btnDelete_Click _
(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnDelete.Click

Dim objConnect As New SqlConnection
Dim objCommand As New SqlCommand
Dim strMessage As String ---- 確認用メッセージを保存
Dim strSql As String -------- SQLを保存

↓削除用の接続文字列を設定
strSql = "DELETE 商品_dmy WHERE 商品ID = " & strTargetId

↓ユーザー宛の確認メッセージ
strMessage = "商品ID:" & strTargetId & vbCrLf & _
         "品名:" & strTargetName & vbCrLf & _
         "を削除します。よろしいですか?"

↓まだレコードが検索(特定)されていない場合には処理を行わない
If (btnDelete_Click = "") Or (strTargetName = "") Then
 MsgBox("商品が特定されていません。", MsgBoxStyle.OKOnly, "商品エラー")
 Exit Sub
End If

↓ユーザーに確認を求める
If MsgBox(strMessage, MsgBoxStyle.YesNo, "削除の確認") = MsgBoxResult.No Then
 Exit Sub
End If

Try
 ↓接続文字列の設定
 objConnect.ConnectionString = _
 "Persist Security Info=False;Integrated Security=SSPI;database=db1001ya;server=localhost"
 objCommand.Connection = objConnect
 objConnect.Open()

 ↓DELETE命令を使ったSQLを設定
 objCommand.CommandText = strSql

 If objCommand.ExecuteNonQuery >= 1 Then ---- 削除
実行★
  MsgBox("削除しました。", MsgBoxStyle.OKOnly, "削除完了")
  InitForm() ---- 再実行に備えてテキストボックスとグローバル変数を初期化
 Else
  MsgBox("該当する商品が見つかりません。", MsgBoxStyle.OKOnly, "検索エラー")
  Exit Sub
 End If

 Catch objExcept As Exception
  MsgBox(objExcept.ToString, MsgBoxStyle.OKOnly, "DBエラー")

 Finally
  If Not objConnect Is Nothing Then
  objConnect.Close()
  End If
End Try
End Sub


- 変数とフォームの初期化 -

レコードの削除処理では、同じ処理を何度も繰り返した場合に直前の削除情報が残っていると、間違って「既に削除されたレコードをもう一度削除」される可能性があります。そこで、削除処理を一度実行したら、フォーム上の表示とグローバル変数(削除対象を特定する値)を初期化しておかなければなりません。

この処理は、フォームの初期化時と削除終了時に行う必要があるため、別の下請けプロシージャ“InitForm”として作成します。

Private Sub InitForm()

 strTargetId = ""
 strTargetName = ""
 txtItemId.Text = ""
 lblItemName.Text = "?"
 lblNumStock.Text = "?"
End Sub

これで、「商品_dmy」から指定した商品を削除する処理が出来上がりました。ソースコードの全体像は“ex01Source.txt”を参照してください。



- サンプルの実行結果 -

できあがったアプリケーションを実行してみましょう。

試しに「商品ID=36221/品名=お好み焼きセット」を削除してみます。「商品ID」のテキストボックス(txtItemId)に商品IDを入力して[検索]ボタン(btnSearch)をクリックすると、該当商品が検索されて画面2のようになります。

[削除]ボタン(btnDelete)をクリックすると、まず画面3のような確認メッセージが表示され、ここで[はい]をクリックすれば該当レコードがテーブルから削除されます。結果は画面4のとおりです。


削除確認のメッセージ
画面3:削除確認のメッセージ



あとがき

SELECT命令によるレコードの検索処理とは異なり、データベースの変更を伴う削除などの処理では、処理対象レコードの特定やユーザーに対する確認など、本来の処理以外にも配慮しなければならないことがたくさんあります。

サンプルでは単純に「商品ID」を入力する形としましたが、実際の処理では商品名の一部から曖昧検索をしたり、仕入先を基準にリストから選択できるようにするなど、ユーザーインターフェイスを工夫する必要もあるでしょう。しかし、基本はここで紹介した単純な仕組みです。まず、最低限必要な処理をしっかり把握しておきましょう。


Downloadサンプルファイル (LZH形式 994KB)



トップページ
SqlConnectionとOleDbConnectionの違い(1)
SqlConnectionとOleDbConnectionの違い(2)
テーブルを書き換えるSQLの実行
サンプルアプリケーションの仕様
サンプルアプリケーションの作成
グローバル変数で情報を受け渡す
商品検索処理
検索の下請け処理
レコードの削除処理
変数とフォームの初期化
サンプルの実行結果
あとがき
Copyright © MESCIUS inc. All rights reserved.