Caché は、ダイナミック SQL クエリをサポートしています。ダイナミック SQL は、%Library.ResultSet を使用して実行時に作成、実行されるクエリです。ダイナミック SQL により、Caché でも ODBC や JDBC アプリケーションと同じ方法でプログラムを作成することができます (データベース・エンジンと同じプロセス・コンテキストで、クエリを実行している場合は除きます)。
例えば、以下の Basic のコードは、ダイナミック SQL 文を作成し、実行します。
result = New %Library.ResultSet()
result.Prepare("SELECT Name,SSN FROM Sample.Person ORDER BY Name")
result.Execute()

While (result.Next())
	PrintLn result.Data("Name") & ", " & result.Data("SSN")
Wend
 
ダイナミック SQL の操作方法について、以下で説明します。
ダイナミック SQL と埋め込み SQL
ダイナミック SQL と埋め込み SQL の相違点は以下の通りです。
ダイナミック SQL と埋め込み SQL は同じデータ表示 (既定では論理モードですが、変更できます)、および NULL 処理を使用します。
%Library.ResultSet クラス
ダイナミック SQL は、%Library.ResultSet クラスによってサポートされています。アプリケーションは %Library.ResultSet クラスのインスタンスを生成し、それをクエリの作成、実行、繰り返しに使用します。
%Library.ResultSet オブジェクトの生成
Basic では、New コマンドを使用して %Library.ResultSet クラスのインスタンスを生成することができます。
result = New %Library.ResultSet()
Caché ObjectScript でも同様の操作を実行できます。
 Set result = ##class(%Library.ResultSet).%New()
この時点で %Library.ResultSet オブジェクトは SQL 文を作成できる状態です。
クエリの作成
%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 文などの文を作成できます。
クエリのメタ情報
クエリの準備後、%Library.ResultSet クラスのメソッドを使用して、そのクエリに関するメタ情報を検索することができます。これらのメソッドには以下のものがあります。
GetColumnCount  クエリの中の列数を返します 
GetColumnName  列番号でインデックス付けされた、特定の列の名前を返します 
GetParamCount  クエリに対する入力パラメータ数を返します 
クエリの実行
クエリの準備後、%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 クラスの 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 メソッドを使用して、列番号でインデックス付けされた現在の行のデータを取得できます。
クエリのクローズ
ダイナミック SQL クエリが完了したときには、これをクローズします (クエリが使用したリソースを開放します)。これには、a) %Library.ResultSet オブジェクトを破棄する (有効範囲外に出す) か、b) 明示的に %Library.ResultSet クラスの Close メソッドを呼び出します。
result.Close()
Close メソッドを呼び出すことによって、ユーザは、同じクエリからメソッドを実行し取り出す際に、再度作成する必要がなくなります。
クエリ・キャッシュ
Caché は、頻繁に使用されるダイナミック SQL クエリのキャッシュ (ODBC、JDBC、ダイナミック SQL によって生成されたもの) を、自動的に維持します。
最初に SQL クエリを作成するとき、SQL エンジンはこれを最適化し、クエリを実行するプログラム (1 つ以上の Caché ルーチンのセット) を生成します。その後、クエリ・テキストが、クエリ・キャッシュに置かれます。継続的に同じ (または同様の) クエリを作成する場合、SQL エンジンはこれをキャッシュで見つけ、最適化とコードの生成を飛ばしてクエリのコードを直接実行します。
クエリ・キャッシュには、以下の利点があります。
テーブルが変更 (置換、削除) されると、このテーブルを元にしたクエリは、自動的にクエリ・キャッシュから消去されます。
Caché SQL マネージャ から、クエリ・キャッシュの内容を見る (管理する) ことができます。
埋め込み SQL 文はコンパイル時にインライン・コードと置換されるため、埋め込み SQL をキャッシュする必要はありません。