ダイナミック SQL と埋め込み SQL の相違点は以下の通りです。
• ダイナミック SQL クエリは、コンパイル時ではなく、プログラム実行時に作成されます。つまり、
コンパイラはコンパイル時にエラーのチェックを実行できません。また、プログラムは、ユーザや その他の入力に応答して、専用のクエリを生成できます。
• ダイナミック SQL はクエリ用のインライン・コードを生成しないため、埋め込み SQL よりもやや 非効率的です。
• ダイナミック SQL の入力パラメータは、 “?” を使用して示し、埋め込み SQL はホスト変数 (:var など) を使用します。
• ダイナミック SQL からの出力値は、%Library.ResultSetオブジェクト (つまりDataプロパティ) の API を使用して検索されますが、埋め込み SQL はホスト変数 (:var など) を使用します。
• ダイナミック SQL は、Basic や Caché ObjectScript 内でも使用できます。
• ダイナミック SQL により、クエリのメタ情報 (列の数や名前など) を簡単に見ることができます。
• ダイナミック SQL によって作成されるクエリは、クエリ・キャッシュで維持されるため、後のクエリ が同じクエリを作成する場合は、既に生成されているコードを再利用できます。埋め込み SQL は、コンパイル時にインライン・コードを生成するため、クエリ・キャッシュを使用する必要があり ません。
ダイナミック SQL と埋め込み SQL は同じデータ表示 (既定では論理モードですが、変更できます)、
および NULL 処理を使用します。
10.2 %Library.ResultSet クラス
ダイナミック SQL は、%Library.ResultSetクラスによってサポートされています。アプリケーションは
%Library.ResultSetクラスのインスタンスを生成し、それをクエリの作成、実行、繰り返しに使用しま す。
10.2.1 %Library.ResultSet オブジェクトの生成
Basic では、New コマンドを使用して%Library.ResultSetクラスのインスタンスを生成できます。
result = New %Library.ResultSet()
Caché ObjectScript でも同様の操作を実行できます。
Set result = ##class(%Library.ResultSet).%New()
この時点で%Library.ResultSetオブジェクトは SQL 文を作成できる状態です。
10.2.2 クエリの作成
%Library.ResultSetクラスの Prepare メソッドを使用して、SQL 文の準備ができます。これは、SQL クエリを含む文字列を最初の引数とし、後で実行する準備をします。例えば、Basic では以下の通り です。
result.Prepare("SELECT Name FROM MyApp.Person ORDER BY Name")
Prepare メソッドは、成功 (クエリ文字列が有効な SQL 文を持つ場合)、または失敗 (有効な SQL 文 を持たない場合) を示す%Status値を返します。
“? ” 文字を使用して、入力パラメータ (WHERE 節で使用される変数) を指定できます。
result.Prepare("SELECT Name FROM MyApp.Employee WHERE Salary > ?")
各入力パラメータの値は、クエリが実行されたときに指定されます (次のセクションを参照してくださ い)。
ダイナミック SQL では、SELECT 文に限らず、Prepare メソッドを使用して、DDL、INSERT、UPDATE、
DELETE などの文を作成できます。
10.2.3 クエリのメタ情報
クエリの準備後、%Library.ResultSetクラスのメソッドを使用して、そのクエリに関するメタ情報を検索 できます。これらのメソッドには、以下のものがあります。
説明 メソッド
クエリの中の列数を返します GetColumnCount
列番号でインデックス付けされた、特定の列の名前を返します GetColumnName
クエリに対する入力パラメータ数を返します GetParamCount
10.2.4 クエリの実行
クエリの準備後、%Library.ResultSetクラスの Execute メソッドを呼び出すことで、クエリを実行でき ます。非 SELECT 文の場合、Execute により (INSERT の実行など) 使用する演算を呼び出すこと ができます。SELECT クエリの場合、Execute がクエリを作成し、後の部分の走査とデータの検索が 実行されます。
Execute メソッドは、作成された SQL 文のあらゆる入力パラメータ ( “?” に示される) に対応する引 数の変数の数を取得します。入力パラメータは、 “?” 文字が SQL 文で表示される順序に対応しま す。最初の引数は、最初の “?” に使用され、2 番目の引数は 2 番目の “?” に使用されるという ことです。
例えば、以下の Basic コードは、2 つの入力パラメータを持つクエリを実行します。
result = New %Library.ResultSet()
sql = "SELECT Name FROM MyApp.Employee WHERE Salary > ? AND Salary < ?"
' prepare the query result.Prepare(sql)
'find everyone with salary between 10000 and 20000 result.Execute(10000,20000)
Execute メソッドは、%Status値を返し、成功または失敗を示します。
%Library.ResultSet クラス
10.2.5 クエリからのデータのフェッチ
%Library.ResultSetクラスの Next メソッドを使用して、SELECT クエリの結果を繰り返すことができま す。
While (result.Next())
PrintLn result.Data("Name") Wend
Next メソッドは、クエリの結果の次の行のデータを取り出し、そのデータを%Library.ResultSetオブ ジェクトのDataプロパティに置きます。Next メソッドは、取り出す行がある限り真の値を返します。ク エリ結果の最後に達したときに偽を返します。
Dataプロパティは、列名を添え字に持ち、現在の行に対してフェッチされたデータ値を持つ配列で す。
列名は、SQL クエリによって指定されます。同じ名前の複数の列が存在する場合、Dataプロパティ によって両方を検索することはできません。その代わり、SQL 文内でエイリアスを使用して一意の列 名を与える必要があります。
result = New %Library.ResultSet() ' create the query string
sql = "SELECT A.Name As AName, B.Name As BName "
sql = sql & "FROM MyApp.Table1 A, MyApp.Table2 B "
sql = sql & "WHERE A.Code = B.Code"
' prepare the query result.Prepare(sql)
%Library.ResultSetクラスの GetData メソッドを使用して、列番号でインデックス付けされた現在の 行のデータを取得できます。
10.2.6 クエリのクローズ
ダイナミック SQL クエリが完了したときには、これをクローズします (クエリが使用したリソースを開放 します)。これには、a)%Library.ResultSetオブジェクトを破棄する (有効範囲外に出す) か、b) 明示 的に%Library.ResultSetクラスの Close メソッドを呼び出します。
result.Close()
Close メソッドを呼び出すことによって、ユーザは、同じクエリからメソッドを実行し取り出す際に、再 度作成する必要がなくなります。