2011年4月27日水曜日

SQL Server のテーブルを全て CSV 出力するワークフロー

SQL Server でテーブルの内容を CSV 出力する事はそれなりに頻度があるかと思います。大体は BCP 等のユーティリティを利用して行うとか、それをスクリプトにまとめておくとか、そのような形ではないでしょうか。同じことをワークフローでも表現してみました。

TableToCsv1

今回は次のような流れのワークフローです。

  1. データベースからテーブル一覧を取得
  2. テーブルごとにデータを抽出
  3. 抽出したデータを CSV 出力

テーブル一覧を取得する部分は今回新規に用意したアクティビティですが、それ以外は今までの記事で利用したものとなっています。ロジックはこのような感じです。

1: Imports System.Activities
2: 
3: Public Class GetSQLTableListActivity
4:     Inherits AsyncCodeActivity
5: 
6:     Private Const SQL_GETTABLE = "SELECT * FROM SYS.TABLES"
7: 
8:     Property ConnectionString As InArgument(Of String)
9:     Property Condition As String = ""
10:     Property TableList As OutArgument(Of String())
11: 
12:     Public Sub New()
13:         Me.DisplayName = "SQL Server のテーブル一覧を取得"
14:     End Sub
15: 
16:     Private Delegate Function GetSQLTableListDelegate(ByVal conString As String, ByVal conditionStrings As String) As String()
17: 
18:     Protected Overrides Function BeginExecute(ByVal context As System.Activities.AsyncCodeActivityContext, ByVal callback As System.AsyncCallback, ByVal state As Object) As System.IAsyncResult
19:         Dim conStr = context.GetValue(Me.ConnectionString)
20:         Dim asyncGetSQLTableListDel = New GetSQLTableListDelegate(AddressOf GetSQLTableList)
21:         context.UserState = asyncGetSQLTableListDel
22: 
23:         Return asyncGetSQLTableListDel.BeginInvoke(conStr, Me.Condition, callback, state)
24:     End Function
25: 
26:     Protected Overrides Sub EndExecute(ByVal context As System.Activities.AsyncCodeActivityContext, ByVal result As System.IAsyncResult)
27:         Dim asyncGetSQLTableListDel = TryCast(context.UserState, GetSQLTableListDelegate)
28:         Dim resultStrings = asyncGetSQLTableListDel.EndInvoke(result)
29:         TableList.Set(context, resultStrings)
30:     End Sub
31: 
32:     Private Function GetSQLTableList(ByVal conString As String, ByVal conditionStrings As String) As String()
33:         Dim result As String()
34: 
35:         Dim tabList As New DataSet
36:         Try
37:             Using sqlConn As New SqlClient.SqlConnection(conString)
38:                 sqlConn.Open()
39:                 'テーブル一覧の取得
40:                 Dim execSql As String = SQL_GETTABLE
41:                 If conditionStrings.Trim <> "" Then
42:                     execSql += " WHERE name like '%" + conditionStrings + "%'"
43:                 End If
44:                 execSql += " ORDER BY name "
45: 
46:                 Dim dataAdapter As New SqlClient.SqlDataAdapter
47:                 dataAdapter.SelectCommand = New SqlClient.SqlCommand(execSql, sqlConn)
48:                 dataAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey
49:                 dataAdapter.Fill(tabList)
50:                 sqlConn.Close()
51:             End Using
52:         Catch ex As Exception
53: 
54:         End Try
55:         '結果を String() に出力
56:         If tabList.Tables.Count > 0 Then
57:             Dim resultList As New List(Of String)
58:             For Each childRow In tabList.Tables(0).Rows
59:                 resultList.Add(childRow.item("name").ToString)
60:             Next
61:             result = resultList.ToArray
62:         Else
63:             result = Nothing
64:         End If
65: 
66:         Return result
67:     End Function
68: 
69: End Class

SQL Server  では SELECT * FROM SYS.TABLES とすることでテーブル一覧が取得できますので、その結果を今回は String の配列として返却するようにしています。

そうして得たテーブル一覧に対して ForEach アクティビティでループ、その内部では取得したテーブル名を元にデータを取得、その結果を利用して ForEach アクティビティで更にループ、以前利用した CSVOutput なアクティビティを利用して1行ずつファイルへと出力しています。

このようにワークフローとして処理を記述すると、スクリプトやツールの知識がなくとも行われている処理内容が非常にイメージしやすくなります。このあたりが Workflow の醍醐味なのではないか、と個人的には思っています。

0 件のコメント:

コメントを投稿