fc2ブログ

2014年01月 の記事一覧

長いSelect文をストアドに保持させる(MySQL+VB.net)

最近OracleのデータをMySQLに移行しているが、以前の記事で書いた(VBAでRefCursorのデータ操作(ADO版))長いSelect文だけをストアドで保持する方法をMySqlで出来ないかな?と探していたら、簡単にできることがわかった。という事でVB.netでちょっとSelectしてみるとこまでやってみる。

ちなみに現在の開発環境
・Windows7 Ultimate
・Microsoft Visual Studio Express 2012 for Windows Desktop
・MySQL CommunityServer5.1.73


■1.DB側の準備


MySQLで適当にsampledbというデータベースを作成して、vbというユーザにsampleというテーブルを作成し、sampleテーブルをSelectするプロシージャを作成。

(1) DBとユーザ作成

コマンドプロンプトでrootユーザで下記を実行

>mysql -u root -pパスワード
mysql>create database sampledb;
mysql>grant all on sampledb.* to vb@localhost identified by 'vb';


(2) テーブルとサンプルデータ作成

続いてvbユーザでテーブルを作成

>mysqlt -u vb -pvb sampledb;
mysql>create table sample(user_id int primary key, user_name varchar(40), message varchar(200));
mysql>insert into sample values (1, 'hoge-a', 'good morning.'), (2, 'hoge-b', 'good evening.');


(3) プロシージャの作成

vbユーザのままProcedureを作成。
パッケージはMySQLには無いので、stored_sampleというプロシージャを作成。create前には必ずdelimiterを変更。

mysql>delimiter //
mysql>create procedure stored_sample(in set_user_id int)
      begin
          select * from sample where user_id = set_user_id; /* ① 保持したいSQL文 */
      end;
mysql>//
mysql>delimiter ;


指定のuser_idのデータをSelectするような形にしてみる(以前の記事(VBAでRefCursorのデータ操作(ADO版))と同じ)。
①の部分が目的の保持したいSQL文になる。MySQLだとRefCusorとか何の小細工も無くSelect文を置くだけ…。


■2.VB.net側の準備

(1) Visual Studio Express 2012 for Windows Desktopを開いて、新規でwindowsフォームアプリケーションを作成。
(2) メニューバーから「ツール」→「ライブラリ パッケージ マネージャ」→「ソリューションのNuGetパッケージの管理」を開く。
(3) オンラインで「MySql」を検索して「MySql.Data」ドライバをインストールする。
(4) フォーム(Form1.vb)にDataGridViewを貼り付ける(コントロール名:DataGridView1)。

20140113_01.jpg

(5) フォーム(Form1.vb)のコードを表示して以下を追記。

Imports MySql.Data.MySqlClient
Public Class Form1
    Public Sub New()
        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        Construct()
    End Sub

    Private Sub Construct()
        Dim ds As New DataSet

        ' sampleデータ取得
        Using cmd As New MySqlCommand
            Try
                cmd.CommandType = CommandType.StoredProcedure ' ②
                cmd.CommandText = "stored_sample"
                cmd.Connection = New MySqlConnection("Database=sampledb;Data Source=localhost;User Id=vb;Password=vb")
                cmd.Parameters.Add("set_user_id", MySqlDbType.Int32).Value = 2 ' ③ user_id=2を抽出

                Using da As New MySqlDataAdapter
                    da.SelectCommand = cmd
                    da.Fill(ds, "sample")
                End Using
            Catch ex As MySqlException
                Throw ex
            End Try
        End Using

        DataGridView1.DataSource = ds.Tables("sample")
    End Sub
End Class


②でコマンドタイプをStoredProcedureにして、③でプロシージャの引数set_user_idに指定のuser_id番号を渡してSelect文を実行。
その結果をDataGridViewで表示してるだけ。

実行してみると、

20140113_02.jpg

のような感じでuser_id=2のデータが取得できる。

ちなみにMySQLってfull outer joinできないのかぁ。with句も使えないみたいだし、またSQLが汚くて長くなるなぁ・・・(って自分のセンスの問題だけど)。

スポンサーサイト



DataGridViewCheckBoxCellをクリックするだけでチェック状態を切り替えるようにする

最近DataGridViewをちょこちょこ弄っているが、チェックボックスセル(DataGridViewCheckBoxCell)のチェック枠でクリックした時に反応が鈍くてチェックされた状態にならない場合もあるので、セルをクリックしたらチェックされた状態になるように修正してみた。

(1) 「Microsoft Visual Studio Express 2012 for Windows Desktop」を開き、新規で「Windowsフォームアプリケーション」を開く。

(2) ソリューションエクスプローラから新規でクラスを追加して(クラス名はDataGridViewCheckBoxCellEx)、以下のコードを追記。

Public Class DataGridViewCheckBoxCellEx
    Inherits DataGridViewCheckBoxCell

    Protected Overrides Sub OnClick(ByVal e As System.Windows.Forms.DataGridViewCellEventArgs)
        MyBase.OnClick(e)
        Dim bBool As Boolean = Me.Value Xor True
        Me.Value = bBool
        Me.DataGridView.CurrentCell = Me.DataGridView(e.ColumnIndex + 1, e.RowIndex) ' ①
    End Sub

End Class


(3) Form1.vbのデザインを開きツールボックスからDataGridViewを選択し適当にフォームに貼り付ける。(コントロール名はDataGridView1)

(4) Form1.vbに以下のコードを追記

Public Class Form1
    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        construct()
    End Sub

    Private Sub Construct()
        ' 適当にセル作成
        With DataGridView1
            For iCol As Integer = 0 To 3
                .Columns.Add(iCol.ToString, iCol.ToString)
                .Columns(iCol).Width = 120
            Next
            .Rows.Add(5)
            .CurrentCell = DataGridView1(0, 1)
        End With
        ' CheckBoxCellを入れる
        Dim chkCell As New DataGridViewCheckBoxCellEx
        chkCell.Value = False
        DataGridView1(0, 0) = chkCell
    End Sub
End Class


(5) ソリューションをビルド

内容はDataGridViewCheckBoxCellを継承したクラスを作って、OnClickイベントでチェックされていない場合はValue値をTrueに、チェックされてる場合はValue値をFalseに変えてるだけだが、①でセルの位置を一つ右にずらしてやってる。

理由としては、カレントセルをずらさないとチェックの描画が走らないので、見た目上チェックされているのかされてないのかが分からないから(Refresh, Update等やっても再描画が走らないので苦肉の策…)。

またカレントセルをチェックボックスセルに戻した方が良いのでは?と思うけれども、クリック後にチェック枠を正確にクリックするとOnClickとは別にチェック描画が走ってしまい、見た目上はチェックされてるのにソース上ではValue値がFalseというギャップが発生してしまうので、戻すコードは追記してはいけない。

どうも描画系イベントは不明点だらけ。セル結合の時も乱れることあるし…あまり手を突っ込みたくない部分。


DataGridViewCheckBoxCellにキャプションを付ける

最近DataGridViewをちょこちょこ弄っているが、チェックボックスが表示されるセル(DataGridViewCheckBoxCell)にキャプションを付けたくなった。が、Captionというプロパティがこのセルに無い(セルだからかな…)ので作ってみた。

(1) 「Microsoft Visual Studio Express 2012 for Windows Desktop」を開き、新規で「Windowsフォームアプリケーション」を開く。

(2) ソリューションエクスプローラから新規でクラスを追加して(クラス名はDataGridViewCheckBoxCellEx)、以下のコードを追記。

Public Class DataGridViewCheckBoxCellEx
    Inherits DataGridViewCheckBoxCell

    Private _caption As String

    Public Property Caption As String
        Set(value As String)
            _caption = value
        End Set
        Get
            Return _caption
        End Get
    End Property

    Protected Overrides Sub Paint(graphics As Graphics, clipBounds As Rectangle, cellBounds As Rectangle, rowIndex As Integer, elementState As DataGridViewElementStates, value As Object, formattedValue As Object, errorText As String, cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle, paintParts As DataGridViewPaintParts)

        MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
        ' ① Xを+20ずらしてキャプションを描画
        Dim indexRect As Rectangle = cellBounds
        indexRect.X += +20
        TextRenderer.DrawText(graphics, _caption, cellStyle.Font, indexRect, cellStyle.ForeColor, TextFormatFlags.Left Or TextFormatFlags.VerticalCenter)

    End Sub
End Class


(3) Form1.vbのデザインを開きツールボックスからDataGridViewを選択し適当にフォームに貼り付ける。(コントロール名はDataGridView1)

20140103_01.jpg

(4) Form1.vbに以下のコードを追記

Public Class Form1
    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        construct()
    End Sub

    Private Sub Construct()
        ' 適当にセル作成
        With DataGridView1
            For iCol As Integer = 0 To 3
                .Columns.Add(iCol.ToString, iCol.ToString)
                .Columns(iCol).Width = 120
            Next
            .Rows.Add(5)
            .CurrentCell = DataGridView1(0, 1)
        End With
        ' キャプションを付ける
        Dim chkCell As New DataGridViewCheckBoxCellEx
        With chkCell
            .Caption = "サンプルキャプション"
            .Value = True
        End With
        DataGridView1(0, 0) = chkCell
    End Sub
End Class


(5) ソリューションをビルド

内容はDataGridViewCheckBoxCellを継承したクラスを作って、Paintイベント内で①のようにXをずらしてDrawTextでキャプションを表示してるだけ(Xはチェックボックスを跨ぐ座標軸)。

実行してみると…

20140103_02.jpg  
 
のような感じになる。
注意点としてはAlignが左詰め専用ということと、キャプションが表示できるぐらいのセル幅(width)を持たせるということ。