Visual BasicでCLRプロシージャーを作成する際には、以下の例を参考に利用してください。
- Visual Basicの外部コード・ファイル
- 例1: パラメーター・スタイルGENERALを使用するVisual Basicのプロシージャー
- 例2: パラメーター・スタイルSQLを使用するVisual Basicのプロシージャー
- 例3: PROGRAM TYPE MAINを使用するVisual Basicのプロシージャー
この例では、Visual Basicによるさまざまなプロシージャーのインプリメンテーションを紹介します。それぞれの例はCREATE PROCEDUREステートメントと、関連するアセンブリーをビルドする際にソースとして使用するVisual Basicによるプロシージャーの外部コードのインプリメンテーションという2つの部分から構成されています。
以下の例では、gwenVbProc.vbというVisual Basicのソース・ファイルにプロシージャーのインプリメンテーションが含まれています。このファイルの形式は以下のとおりです。
Visual Basicの外部コード・ファイルの形式
using System;
using System.IO;
using IBM.Data.DB2;
Namespace bizLogic
Class empOps
...
' Visual Basic procedures
...
End Class
End Namespace
|
このファイルの最上部では、ファイルの組み込みを指定しています。ファイル内にSQLを使用しているプロシージャーがある場合は、IBM.Data.DB2を組み込む必要があります。このファイルには、ネームスペースの宣言と、プロシージャーが含まれているクラスempOpsの宣言があります。ネームスペースは必要に応じて使用します。ネームスペースを使用する場合は、CREATE PROCEDUREステートメントのEXTERNAL文節で指定するアセンブリーのパス名にネームスペースが含まれていなければなりません。
プロシージャーのインプリメンテーションで使用しているファイルの名前、ネームスペース、クラスの名前は書きとめておくことが重要です。これらの名前は、DB2がCLRプロシージャーのアセンブリーやクラスを見つけ出せるように、各プロシージャーに関するCREATE PROCEDUREステートメントのEXTERNAL文節で指定する必要があるので重要な意味を持ちます。
例1: パラメーター・スタイルGENERALを使用するVisual Basicのプロシージャー
この例では、以下のものを示しています。
- パラメーター・スタイルGENERALのプロシージャーを作成するCREATE PROCEDUREステートメント
- パラメーター・スタイルGENERALのプロシージャーを記述したVisual Basicのコード
このプロシージャーは、従業員IDと現在の賞与額を入力として受け取り、従業員の名前と給与額を検索します。現在の賞与額がゼロの場合は、その従業員の給与額に基づいて新たな賞与額を算出し、その賞与額を従業員のフルネームとともに返します。該当する従業員が見つからなかった場合は、空のストリングを返します。
パラメーター・スタイルGENERALのVisual Basicのプロシージャー作成するコード
CREATE PROCEDURE SetEmpBonusGEN(IN empId CHAR(6),
INOUT bonus Decimal(9,2),
OUT empName VARCHAR(60))
SPECIFIC setEmpBonusGEN
LANGUAGE CLR
PARAMETER STYLE GENERAL
DYNAMIC RESULT SETS 0
FENCED
PROGRAM TYPE SUB
EXTERNAL NAME 'gwenVbProc.dll:bizLogic.empOps!SetEmpBonusGEN'
EXECUTION CONTROL SAFE ;
|
Public Shared Sub SetEmpBonusGEN(ByVal empId As String, _
ByRef bonus As Decimal, _
ByRef empName As String)
Dim salary As Decimal
Dim myCommand As DB2Command
Dim myReader As DB2DataReader
salary = 0
myCommand = DB2Context.GetCommand()
myCommand.CommandText = _
"SELECT FIRSTNME, MIDINIT, LASTNAME, SALARY " _
+ "FROM EMPLOYEE " _
+ "WHERE EMPNO = '" + empId + "'"
myReader = myCommand.ExecuteReader()
If myReader.Read() ' If employee record is found
' Get the employee's full name and salary
empName = myReader.GetString(0) + " " _
+ myReader.GetString(1) + ". " _
+ myReader.GetString(2)
salary = myReader.GetDecimal(3)
If bonus = 0
If salary > 5000
bonus = salary * 0.025
Else
bonus = salary * 0.05
End If
End If
Else ' Employee not found
empName = "" ' Set output parameter
End If
myReader.Close()
End Sub
|
例2: パラメーター・スタイルSQLを使用するVisual Basicのプロシージャー
この例では、以下のものを示しています。
- パラメーター・スタイルSQLのプロシージャーを作成するCREATE PROCEDUREステートメント
- パラメーター・スタイルSQLのプロシージャーを記述したVisual Basicのコード
このプロシージャーは、従業員IDと現在の賞与額を入力として受け取り、従業員の名前と給与額を検索します。現在の賞与額がゼロの場合は、給与額に基づいて新たな賞与額を算出し、その賞与額を従業員のフルネームとともに返します。該当する従業員が見つからなかった場合は、空のストリングを返します。
パラメーター・スタイルSQLのVisual Basicのプロシージャーを作成するコード
CREATE PROCEDURE SetEmpBonusSQL(IN empId CHAR(6),
INOUT bonus Decimal(9,2),
OUT empName VARCHAR(60))
SPECIFIC SetEmpBonusSQL
LANGUAGE CLR
PARAMETER STYLE SQL
DYNAMIC RESULT SETS 0
FENCED
PROGRAM TYPE SUB
EXTERNAL NAME 'gwenVbProc.dll:bizLogic.empOps!SetEmpBonusSQL'
EXECUTION CONTROL SAFE ;
|
Public Shared Sub SetEmpBonusSQL(byVal empId As String, _
byRef bonus As Decimal, _
byRef empName As String, _
byVal empIdNullInd As Int16, _
byRef bonusNullInd As Int16, _
byRef empNameNullInd As Int16, _
byRef sqlState As String, _
byVal funcName As String, _
byVal specName As String, _
byRef sqlMessageText As String)
' Declare local host variables
Dim salary As Decimal
Dim myCommand As DB2Command
Dim myReader As DB2DataReader
salary = 0
If empIdNullInd = -1 ' Check if the input is null
bonusNullInd = -1 ' Return a NULL Bonus value
empName = ""
empNameNullInd = -1 ' Return a NULL empName value
Else
myCommand = DB2Context.GetCommand()
myCommand.CommandText = _
"SELECT FIRSTNME, MIDINIT, LASTNAME, SALARY " _
+ "FROM EMPLOYEE " _
+ " WHERE EMPNO = '" + empId + "'"
myReader = myCommand.ExecuteReader()
If myReader.Read() ' If employee record is found
' Get the employee's full name and salary
empName = myReader.GetString(0) + " "
+ myReader.GetString(1) _
+ ". " + myReader.GetString(2)
empNameNullInd = 0
salary = myReader.GetDecimal(3)
If bonus = 0
If salary > 5000
bonus = salary * 0.025
bonusNullInd = 0 ' Return a non-NULL value
Else
bonus = salary * 0.05
bonusNullInd = 0 ' Return a non-NULL value
End If
End If
Else ' Employee not found
empName = "" ' Set output parameter
empNameNullInd = -1 ' Return a NULL value
End If
myReader.Close()
End If
End Sub
|
例3: PROGRAM TYPE MAINスタイルを使用するVisual Basicのプロシージャー
この例では、以下のものを示しています。
- メイン・プログラム方式を使用するプロシージャーを作成するCREATE PROCEDUREステーメント
- パラメーター・スタイルGENERAL WITH NULLSとメイン・プログラム方式を使用するVisual Basicのコード
メイン・プログラム方式のルーチンをインプリメントするには、CREATE PROCEDUREステートメントのPROGRAM TYPE文節の値に「MAIN」を指定する必要があります。パラメーターは、CREATE PROCEDUREステートメント内で指定しますが、コードのインプリテーションでは、integer型パラメーターargcおよびパラメーター配列argvによってパラメーターがルーチンに渡されます。
PROGRAM TYPE MAINスタイルのVisual Basicのプロシージャーを作成するコード
CREATE PROCEDURE MainStyle(IN empId CHAR(6),
INOUT bonus Decimal(9,2),
OUT empName VARCHAR(60))
SPECIFIC mainStyle
DYNAMIC RESULT SETS 0
LANGUAGE CLR
PARAMETER STYLE GENERAL WITH NULLS
FENCED
PROGRAM TYPE MAIN
EXTERNAL NAME 'gwenVbProc.dll:bizLogic.empOps!Main'
EXECUTION CONTROL SAFE ;
|
Public Shared Sub Main( byVal argc As Int32, _
byVal argv As Object())
Dim myCommand As DB2Command
Dim myReader As DB2DataReader
Dim empId As String
Dim bonus As Decimal
Dim salary As Decimal
Dim nullInds As Int16()
empId = argv(0) ' argv[0] (IN) nullInd = argv[3]
bonus = argv(1) ' argv[1] (INOUT) nullInd = argv[4]
' argv[2] (OUT) nullInd = argv[5]
salary = 0
nullInds = argv(3)
If nullInds(0) = -1 ' Check if the empId input is null
nullInds(1) = -1 ' Return a NULL Bonus value
argv(1) = "" ' Set output parameter empName
nullInds(2) = -1 ' Return a NULL empName value
Return
Else
' If the employee exists and the current bonus is 0,
' calculate a new employee bonus based on the employee's
' salary. Return the employee name and the new bonus
myCommand = DB2Context.GetCommand()
myCommand.CommandText = _
"SELECT FIRSTNME, MIDINIT, LASTNAME, SALARY " _
+ " FROM EMPLOYEE " _
+ " WHERE EMPNO = '" + empId + "'"
myReader = myCommand.ExecuteReader()
If myReader.Read() ' If employee record is found
' Get the employee's full name and salary
argv(2) = myReader.GetString(0) + " " _
+ myReader.GetString(1) + ". " _
+ myReader.GetString(2)
nullInds(2) = 0
salary = myReader.GetDecimal(3)
If bonus = 0
If salary > 5000
argv(1) = salary * 0.025
nullInds(1) = 0 ' Return a non-NULL value
Else
argv(1) = Salary * 0.05
nullInds(1) = 0 ' Return a non-NULL value
End If
End If
Else ' Employee not found
argv(2) = "" ' Set output parameter
nullInds(2) = -1 ' Return a NULL value
End If
myReader.Close()
End If
End Sub
|
Visual Basicでユーザー独自のCLR UDFを作成する際には、以下の例を参考に利用してください。
- Visual Basicの外部コード・ファイル
- 例1: パラメーター・スタイルSQLを使用するVisual Basicの表関数
- 例2: パラメーター・スタイルSQLを使用するVisual Basicのスカラー関数
以下の例では、Visual BasicによるUDFのさまざまなインプリメンテーションを紹介しています。それぞれのUDFごとに、CREATE FUNCTIONステートメントを示すとともに、関連するアセンブリーをビルドする際にソース・コードとして使用する、対応するVisual Basicのコードを示しています。以下の例で使用する関数の宣言は、gwenVbUDF.csというVisual Basicのソース・ファイルに含まれています。このファイルの形式は以下のとおりです。
Visual Basicの外部コード・ファイルの形式
using System;
using System.IO;
using IBM.Data.DB2;
Namespace bizLogic
...
' Class definitions that contain UDF declarations
' and any supporting class definitions
...
End Namespace
|
関数の宣言は、Visual Basicファイル内のクラスに含まれていなければなりません。ネームスペースは必要に応じて使用します。ネームスペースを使用する場合は、CREATE PROCEDUREステートメントのEXTERNAL文節で指定するアセンブリーのパス名の中にネームスペースが含まれていなければなりません。関数でSQLを使用する場合は、IBM.Data.DB2を組み込む必要があります。
例1: パラメーター・スタイルSQLを使用するVisual Basicの表関数
この例では、以下のものを示しています。
- パラメーター・スタイルSQLの表関数を作成するCREATE FUNCTIONステートメント
- パラメーター・スタイルSQLの表関数を記述したVisual Basicのコード
この表関数は、データ配列から作成された従業員データの行を格納した表を返します。この例には、関連する2つのクラスがあります。クラスpersonは従業員を表し、クラスempOpsにはクラスpersonを使用するユーザー定義の表関数が含まれています。従業員の給与情報は、入力パラメーターの値に基づいて更新されます。この例で使用するデータ配列は、この表関数が最初に呼び出されたときに表関数自体の中で作成されます。ファイル・システム上のテキスト・ファイルからデータを読み込むことによって、このような配列を作成する方法も考えられます。この表関数の後続の呼び出しでデータにアクセスできるように、配列のデータ値はスクラッチパッドに書き込まれます。
この表関数が呼び出されるたびに、配列から1行分のレコードが読み出され、この関数が返す表の中に1つの行が生成されます。表関数の出力パラメーターを必要な行の値に設定することによって、表の中に行が生成されます。この表関数の最後の呼び出しが行われた後で、生成された行を含む表が返されます。
パラメーター・スタイルSQLを使用するVisual Basicの表関数を作成するコード
CREATE FUNCTION TableUDF(double)
RETURNS TABLE (name varchar(20),
job varchar(20),
salary double)
EXTERNAL NAME 'gwenVbUDF.dll:bizLogic.empOps!TableUDF'
LANGUAGE CLR
PARAMETER STYLE SQL
NOT DETERMINISTIC
FENCED
SCRATCHPAD 10
FINAL CALL
DISALLOW PARALLEL
NO DBINFO
EXECUTION CONTROL SAFE
|
Class Person
' The class Person is a supporting class for
' the table function UDF, tableUDF, below.
Private name As String
Private position As String
Private salary As Int32
Public Sub New(ByVal newName As String, _
ByVal newPosition As String, _
ByVal newSalary As Int32)
name = newName
position = newPosition
salary = newSalary
End Sub
Public Property GetName() As String
Get
Return name
End Get
Set (ByVal value As String)
name = value
End Set
End Property
Public Property GetPosition() As String
Get
Return position
End Get
Set (ByVal value As String)
position = value
End Set
End Property
Public Property GetSalary() As Int32
Get
Return salary
End Get
Set (ByVal value As Int32)
salary = value
End Set
End Property
End Class
|
Class empOps
Public Shared Sub TableUDF(byVal factor as Double, _
byRef name As String, _
byRef position As String, _
byRef salary As Double, _
byVal factorNullInd As Int16, _
byRef nameNullInd As Int16, _
byRef positionNullInd As Int16, _
byRef salaryNullInd As Int16, _
byRef sqlState As String, _
byVal funcName As String, _
byVal specName As String, _
byRef sqlMessageText As String, _
byVal scratchPad As Byte(), _
byVal callType As Int32)
Dim intRow As Int16
intRow = 0
' Create an array of Person type information
Dim staff(2) As Person
staff(0) = New Person("Gwen", "Developer", 10000)
staff(1) = New Person("Andrew", "Developer", 20000)
staff(2) = New Person("Liu", "Team Leader", 30000)
' Initialize output parameter values and NULL indicators
salary = 0
name = position = ""
nameNullInd = positionNullInd = salaryNullInd = -1
Select callType
Case -2 ' Case SQLUDF_TF_FIRST:
Case -1 ' Case SQLUDF_TF_OPEN:
intRow = 1
scratchPad(0) = intRow ' Write to scratchpad
Case 0 ' Case SQLUDF_TF_FETCH:
intRow = scratchPad(0)
If intRow > staff.Length
sqlState = "02000" ' Return an error SQLSTATE
Else
' Generate a row in the output table
' based on the staff array data.
name = staff(intRow).GetName()
position = staff(intRow).GetPosition()
salary = (staff(intRow).GetSalary()) * factor
nameNullInd = 0
positionNullInd = 0
salaryNullInd = 0
End If
intRow = intRow + 1
scratchPad(0) = intRow ' Write scratchpad
Case 1 ' Case SQLUDF_TF_CLOSE:
Case 2 ' Case SQLUDF_TF_FINAL:
End Select
End Sub
End Class
|
例2: パラメーター・スタイルSQLを使用するVisual Basicのスカラー関数
この例では、以下のものを示します。
- パラメーター・スタイルSQLのスカラー関数を作成するCREATE FUNCTIONステートメント
- パラメーター・スタイルSQLのスカラー関数を記述したVisual Basicのコード
このスカラー関数は、演算の対象となる入力値ごとにカウント値を1つ返します。入力値の集合の中でn番目にある値が渡されると、nという値が出力スカラー値となります。1つの呼び出しが、入力される行または値の集合に含まれている各行または値に関連付けられるので、このスカラー関数が呼び出されるたびに、カウントが1つずつ増やされ、現在のカウント値が返されます。カウントはスクラッチパッドのメモリー・バッファーに保管され、スカラー関数が次回に呼び出されるまで維持されます。
このスカラー関数は、たとえば、以下のように表を定義すれば、簡単に呼び出すことができます。
CREATE TABLE T (i1 INTEGER);
INSERT INTO T VALUES 12, 45, 16, 99;
|
以下のような単純な照会を使用して、スカラー関数を呼び出すことができます。
SELECT my_count(i1) as count, i1 FROM T;
|
この照会の出力は、以下のようになります。
COUNT I1
----------- ----------
1 12
2 45
3 16
4 99
|
このユーザー定義のスカラー関数は非常に単純です。行のカウントだけを返す代わりに、スカラー関数を使用して既存の列のデータを一定の形式にすることもできます。たとえば、address列のそれぞれの値にストリングを付加したり、一連の入力ストリングから複雑なストリングを組み立てたりできるほか、データの集合に対して複雑な数学的評価を行うことも可能です(ただし、この場合は、中間結果を保管する必要があります)。
パラメーター・スタイルSQLを使用するVisual Basicのスカラー関数を作成するコード
CREATE FUNCTION mycount(INTEGER)
RETURNS INTEGER
LANGUAGE CLR
PARAMETER STYLE SQL
FENCED
SCRATCHPAD 10
FINAL CALL
VARIANT
NO SQL
EXTERNAL NAME 'gwenUDF.dll:bizLogic.empOps!CountUp'
EXECUTION CONTROL SAFE;
|
Class empOps
Public Shared Sub CountUp(byVal input As Int32, _
byRef outCounter As Int32, _
byVal nullIndInput As Int16, _
byRef nullIndOutCounter As Int16, _
byRef sqlState As String, _
byVal qualName As String, _
byVal specName As String, _
byRef sqlMessageText As String, _
byVal scratchPad As Byte(), _
byVal callType As Int32)
Dim counter As Int32
counter = 1
Select callType
case -1 ' case SQLUDF_TF_OPEN_CALL
scratchPad(0) = counter
outCounter = counter
nullIndOutCounter = 0
case 0 'case SQLUDF_TF_FETCH_CALL:
counter = scratchPad(0)
counter = counter + 1
outCounter = counter
nullIndOutCounter = 0
scratchPad(0) = counter
case 1 'case SQLUDF_CLOSE_CALL:
counter = scratchPad(0)
outCounter = counter
nullIndOutCounter = 0
case Else ' Should never enter here
' These cases won't occur for the following reasons:
' Case -2 (SQLUDF_TF_FIRST) ->No FINAL CALL in CREATE stmt
' Case 2 (SQLUDF_TF_FINAL) ->No FINAL CALL in CREATE stmt
' Case 255 (SQLUDF_TF_FINAL_CRA) ->No SQL used in the function
'
' * Note!*
' ---------
' The Else is required so that at compile time
' out parameter outCounter is always set *
outCounter = 0
nullIndOutCounter = -1
End Select
End Sub
End Class
|
この記事が、DB2の.NET CLRルーチンをインプリメントしようとする読者のお役に立てば幸いです。さまざまな例を参照しながら、DB2 .NET Data Providerに関するさらに興味深い情報とともにDB2 UDB V8.2sdで提供されるサンプル・アプリケーションを完成させてみてください。
- DB2 Universal Database for Linux, UNIX, and Windows - Stinger
- DB2 Universal Database for Linux, UNIX, and Windows - Version 8.1
- DB2 Information Center - primary source of DB2 product information
- Developing DB2 CLR procedures in VS.NET(英文)
- Developing DB2 UDB procedures with VS.NET Add-ins(英文)
- Developing DB2 Applications with .NET(英文)
- DB2 .NET Data Provider Objects(英文)
-
developerWorks Japan: Information Management : Information Managementの日本語技術情報サイトです
-
developerWorks: Information Management(US) : Information Managementの英語の技術情報サイトです