#60 SQL Serverアップサイズトライアル(5)

「アップサイジングウィザード」に代わるプログラムの5回目です。
今回は、Accessデータベース内からアップサイズ対象とするクエリ情報を収集して、SQL Server上に各種のオブジェクトを生成してみます。


クエリ一覧の取得と種類による選別

まず、Accessデータベース内にあるクエリの一覧を取得します。
データベースの「QueryDefs」コレクションから「QueryDef」オブジェクトを取得することで、1つずつのクエリの定義を取り出します。
さらに、QueryDefの「Name」プロパティで”クエリ名”を、「Type」プロパティで”クエリの種類”を、また「Parameters」コレクションの「Count」プロパティで”パラメータの数”を取得します。

次のプログラムでは最初のステップとしてその結果をイミディエイトウィンドウに出力するだけですが、最終的にはSQL Server上に各種のオブジェクトを生成するものとして、それに関連した分岐処理やプロパティ取得を行っています。

Sub TrySample_5_1()

  Dim dbs As Database
  Dim qdf As QueryDef

  Set dbs = CurrentDb
  For Each qdf In dbs.QueryDefs
    With qdf
      If Left$(.Name, 4) <> "~sq_" Then
        Debug.Print .Name,
        Select Case .Type
          Case dbQSelect
            Debug.Print "選択クエリ",
            If .Parameters.Count = 0 Then
              Debug.Print "パラメータなし"
            Else
              Debug.Print "パラメータあり"
            End If
          Case dbQAppend
            Debug.Print "追加クエリ"
          Case dbQUpdate
            Debug.Print "更新クエリ"
          Case dbQDelete
            Debug.Print "削除クエリ"
          Case Else
            Debug.Print "その他"
        End Select
      End If
    End With
  Next qdf

End Sub




CREATE文の生成と発行

上記のプログラムを展開して、クエリの種類に応じて実際にSQL Severに「CREATE」文を発行し、各オブジェクトを生成します。

ここで生成するCREATE文は次の3種類です。
  1. ビューの生成CREATE VIEW
  2. ストアドファンクションの生成CREATE FUNCTION
  3. ストアドプロシージャの生成CREATE PROCEDURE
  • パラメータがない選択クエリは『ビュー』として生成します。
  • パラメータがある選択クエリは『ストアドファンクション』(テーブル値関数)として生成します。
    ストアドプロシージャでもよいのですが、Accessのクエリと同様に「SELECT * FROM クエリ名」のように使えるよう、ここではストアドファンクションとします。
    ※最後にカッコを付けて「SELECT * FROM ストアドファンクション名()」のように使えます。
  • 追加/更新/削除のいわゆるアクションクエリは『ストアドプロシージャ』として生成します。
  • その他の種類のクエリについては今回は考えないものとします。

CREATE文の組み立てにおいては、QueryDefオブジェクトの「SQL」プロパティを参照、それによってクエリのSQL文を取得・加工することでSQL Serverの文法に対応したSQL文を生成します。

その実際のプログラム例が下記のものとなります。

Sub TrySample_5_2()

  Dim dbsServer As Database
  Dim dbsLocal As Database
  Dim strConStr As String
  Dim qdf As QueryDef
  Dim strQdfSQL As String
  Dim strSQL As String
  Dim strPrmName As String
  Dim strPrmType As String

  strConStr = "ODBC;DRIVER=SQL Server;" & _
              "SERVER=NAFUREI;" & _
              "DATABASE=UpSizeTest;" & _
              "Trusted_Connection=Yes;"

  On Error GoTo Err_Handler

  'SQL Server上のUpSizeTestデータベースに接続
  Set dbsServer = OpenDatabase("", False, False, strConStr)

  Set dbsLocal = CurrentDb
  For Each qdf In dbsLocal.QueryDefs
    strSQL = ""
    With qdf
      If Left$(.Name, 4) <> "~sq_" Then
        'SQLプロパティを取得(最後の;を除去)
        strQdfSQL = Replace(.SQL, ";", "")

        'AccessとSQL Serverの文法の違いを変換
        strQdfSQL = Replace(strQdfSQL, "&", "+")
        strQdfSQL = Replace(strQdfSQL, """", "'")
        strQdfSQL = Replace(strQdfSQL, "True", "1")
        strQdfSQL = Replace(strQdfSQL, "False", "0")

        'ORDER BY句があるときはTOP句を追加
        If InStr(strQdfSQL, "ORDER BY") > 0 And InStr(strQdfSQL, " TOP ") = 0 Then
          strQdfSQL = Replace(strQdfSQL, "SELECT ", "SELECT TOP (100) PERCENT ")
        End If

        'クエリの種類による分岐
        Select Case .Type
          Case dbQSelect
            If .Parameters.Count = 0 Then
              '選択クエリ(パラメータなし)
              strSQL = "CREATE VIEW " & .Name & " AS " & strQdfSQL

            Else
              '選択クエリ(パラメータあり)
              strPrmName = "@" & Replace(Replace(.Parameters(0).Name, "[", ""), "]", "")
              Select Case .Parameters(0).Type
                Case dbText: strPrmType = "nvarchar(255)"
                Case dbByte: strPrmType = "tinyint"
                Case dbInteger: strPrmType = "smallint"
                Case dbLong: strPrmType = "int"
                Case dbSingle: strPrmType = "real"
                Case dbDouble: strPrmType = "float"
                Case dbDate: strPrmType = "datetime"
                Case dbCurrency: strPrmType = "money"
                Case dbBoolean: strPrmType = "bit"
              End Select
              strQdfSQL = Replace(strQdfSQL, .Parameters(0).Name, strPrmName)
              strSQL = "CREATE FUNCTION " & .Name & _
                        " (" & strPrmName & " " & strPrmType & ") " & _
                        "RETURNS TABLE AS " & _
                        "RETURN (" & strQdfSQL & ")"

            End If

          Case dbQAppend, dbQUpdate
            '追加/更新クエリ
            strSQL = "CREATE PROCEDURE " & .Name & " AS " & _
                      "BEGIN " & strQdfSQL & " END"

          Case dbQDelete
            '削除クエリ
            strQdfSQL = "DELETE " & Mid(strQdfSQL, InStr(strQdfSQL, "FROM"))
            strSQL = "CREATE PROCEDURE " & .Name & " AS " & _
                      "BEGIN " & strQdfSQL & " END"

        End Select
      End If
    End With

    If strSQL <> "" Then
      'SQL文をSQL Serverに発行
      dbsServer.Execute strSQL, dbSQLPassThrough
    End If

  Next qdf

Exit_Here:
  Exit Sub

Err_Handler:
  MsgBox "エラー番号:" & Err.Number & vbCrLf & vbCrLf & _
         "エラー内容:" & Err.Description, vbOKOnly + vbCritical
  Resume Exit_Here:

End Sub

  • AccessからCREATE文を発行する際、それがSQL Server上の単純な文法エラーであってもプログラムのエラーが発生します(dbsServer.Execute strSQLの行)。したがって、AccessとSQL Serverの文法上の相違点として考えられる箇所はすべて置き換えておく必要があります(今回はほんの少量のクエリの例に対応しただけです)。
  • ビューやストアドファンクションにおいてはORDER BY句だけではエラーとなります。そのため事前に「TOP (100) PERCENT」を追加しています。
  • 選択クエリ(パラメータあり)では複数のパラメータを考慮すべきですが、今回は”1ケのみ”という前提としています。また、一部のデータ型に限定、テキスト型は長さ255に固定としていますので、あまり汎用性のあるコードにはなっていません。
  • 削除クエリについては、Access側では「DELETE テーブル名.* FROM 〜〜〜」のような構文となりますが、SQL Server用には「DELETE FROM 〜〜〜」のような構文になるようにしています。

ストアドプロシージャ等に関しては、とりあえずできたとしてもいろいろSQL Server側でテストや編集が必要となるかもしれません。またストアドプロシージャのメリットでもあるのですが、Accessで複数のアクションクエリを連続して実行する場合、それらは別々のクエリとして作り1つずつ実行していく必要がありますが、ストアドプロシージャであれば1つのプロシージャ内にそれらをまとめて記述することもできます。他にもそのようなケースは多々ありますので、オブジェクト移行後もSQL Serverならでは機能を活かした改良が必要かもしれません。
また上記はとりあえず出力するだけで、SQLのエディタで見たときのスクリプトの見栄えは考慮されていません。改行やインデントなども出力するプログラム側で実装するか、あるいはSQL Server上にできたものをきれいに整形した方がよいでようです。


実行結果の例:






※クロス集計クエリの”qxrs売上”、テーブル作成クエリの”qmak商品マスタ”は除外されています。

■生成されたビューの例


■生成されたストアドプロシージャの例
| Index | Prev | Next |



Copyright © T'sWare All rights reserved