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 の入力パラメータは、
? を使用して示し、埋め込み SQL はホスト変数 (:var など) を使用します。
-
-
ダイナミック SQL は、Basic や Caché ObjectScript 内でも使用できます。
-
ダイナミック SQL により、クエリのメタ情報 (列の数や名前など) を簡単に見ることができます。
-
ダイナミック SQL によって作成されるクエリは、
クエリ・キャッシュ で維持されるため、後のクエリが同じクエリを作成する場合は、既に生成されているコードを再利用できます。埋め込み SQL は、コンパイル時にインライン・コードを生成するため、クエリ・キャッシュを使用する必要がありません。
ダイナミック SQL と埋め込み SQL は同じデータ表示 (既定では論理モードですが、変更できます)、および NULL 処理を使用します。
%Library.ResultSet オブジェクトの生成
result = New %Library.ResultSet()
Caché ObjectScript でも同様の操作を実行できます。
Set result = ##class(%Library.ResultSet).%New()
result.Prepare("SELECT Name FROM MyApp.Person ORDER BY Name")
? 文字を使用して、入力パラメータ (WHERE 節で使用される変数) を指定できます。
result.Prepare("SELECT Name FROM MyApp.Employee WHERE Salary > ?")
各入力パラメータの値は、クエリが実行されたときに指定されます (次のセクションを参照してください)。
ダイナミック SQL では、SELECT 文に限らず、
Prepare メソッドを使用して、DDL、INSERT、UPDATE、DELETE 文などの文を作成できます。
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)
While (result.Next())
PrintLn result.Data("Name")
Wend
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)
Close メソッドを呼び出すことによって、ユーザは、同じクエリからメソッドを実行し取り出す際に、再度作成する必要がなくなります。
Caché は、頻繁に使用されるダイナミック SQL クエリのキャッシュ (ODBC、JDBC、ダイナミック SQL によって生成されたもの) を、自動的に維持します。
最初に SQL クエリを作成するとき、SQL エンジンはこれを最適化し、クエリを実行するプログラム (1 つ以上の Caché ルーチンのセット) を生成します。その後、クエリ・テキストが、クエリ・キャッシュに置かれます。継続的に同じ (または同様の) クエリを作成する場合、SQL エンジンはこれをキャッシュで見つけ、最適化とコードの生成を飛ばしてクエリのコードを直接実行します。
-
頻繁に使用されるクエリを、より早く継続的に実行できます。さらに、このようなパフォーマンスの向上を
自動的に 利用するために、煩わしいストアド・プロシージャをコードする必要がありません。通常のリレーショナル・データベースは、データベース・アクセスのストアド・プロシージャのみを推奨していますが、Caché では必要ありません。
-
クエリ・キャッシュは、すべてのデータベース・ユーザの間で共有されています。ユーザ 1 がクエリを作成すれば、ユーザ 1023 がこれを使用できます。
-
クエリ・オプティマイザが使用できます。これは、最初にクエリが作成されたときにのみコストを払うため、任意のクエリの実行に最適です。
テーブルが変更 (置換、削除) されると、このテーブルを元にしたクエリは、自動的にクエリ・キャッシュから消去されます。
埋め込み SQL 文はコンパイル時にインライン・コードと置換されるため、埋め込み SQL をキャッシュする必要はありません。