データベースの問い合わせ
この章では、データベースをクエリする方法を説明します。この章には、以下のトピックに関する情報が含まれます。
クエリのタイプ
クエリは、データの取得および結果セットの生成を実行する文です。クエリは、以下のいずれかで構成されます。
SELECT 文の使用法
SELECT 文は、1 つ以上のテーブルまたはビューから 1 つ以上のデータの行を選択します。以下の例では、簡単な SELECT 文を示します。
SELECT Name,DOB FROM Sample.Person WHERE Name %STARTSWITH 'A' ORDER BY DOB
この例では、Name および DOB は Sample.Person テーブル内の列 (データ・フィールド) です。
SELECT 文での節の指定順序は、SELECT DISTINCT TOP ... select-items INTO ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY です。SELECT select-items を除き、これらすべての節はオプションとなります (オプションの FROM 節は、格納されているデータに対する操作の実行に必要なため、クエリではほぼ必ず必要となります)。SELECT 節を指定する際に必要な順序の詳細は、SELECT 文の構文を参照してください。
SELECT 文の操作は、そのセマンティック処理順序に注目すると理解できます (SELECT 構文の順序と同じではありません)。SELECT の節は以下の順序で処理されます。
-
WHERE 節 — さまざまな条件を使用して、選択するデータを制限します。
-
GROUP BY 節 — 選択したデータを一致する値によるサブセットに編成します。値ごとに 1 つのレコードのみが返されます。
-
HAVING 節 — さまざまな条件を使用して、グループから選択するデータを制限します。
-
select-item — 指定したテーブルまたはビューからデータ・フィールドを選択します。select-item は、特定のデータ・フィールドを参照するまたは参照しない式の場合もあります。
-
ORDER BY 節 — さまざまな値で結果をソートします。
このセマンティック順序は、テーブルのエイリアス (FROM 節で定義される) はすべての節で認識できるが、列のエイリアス (SELECT select-items で定義される) は ORDER BY 節でしか認識できないことを示しています。
他の SELECT 節で列のエイリアスを使用するには、以下の例に示すように、サブクエリを使用します。
SELECT Interns FROM
(SELECT Name AS Interns FROM Sample.Employee WHERE Age<21)
WHERE Interns %STARTSWITH 'A'
この例では、Name および Age は Sample.Person テーブル内の列 (データ・フィールド) であり、Interns は Name の列エイリアスです。
フィールドの選択
SELECT を発行すると、Caché SQL は、指定した各 select-item フィールド名を、指定したテーブルに対応するクラスに定義されているプロパティと突き合わせようとします。それぞれのクラス・プロパティには、プロパティ名と SqlFieldName の両方があります。SQL を使用してテーブルを定義した場合、CREATE TABLE コマンドで指定されるフィールド名は SqlFieldName ですが、Caché は SqlFieldName からプロパティ名を生成しています。
フィールド名、クラス・プロパティ名、および SqlFieldName 名には、様々な名前付け規約があります。
-
SELECT 文のフィールド名は、大文字/小文字を区別しません。SqlFieldName 名とプロパティ名は、大文字/小文字を区別します。
-
SELECT 文内のフィールド名と SqlFieldName 名には、識別子の名前付け規約に従う特定の非英数字を含めることができます。プロパティ名には、英数字のみを含めることができます。プロパティ名の生成時に、非英数字は削除されます。固有のプロパティ名を作成するために、Caché が文字を追加することが必要になる場合があります。
フィールドのこれら 3 つの名前間での変換により、クエリ動作のいくつかの面が決定されます。select-item フィールド名は、大文字/小文字の任意の組み合わせで指定でき、Caché SQL は対応する該当のプロパティを識別します。結果セット表示内のデータ列ヘッダ名は SqlFieldName であり、select-item で指定したフィールド名ではありません。この理由から、データ列ヘッダの大文字/小文字は、select-item フィールド名とは異なる場合があります。
大文字/小文字の解決のためのパフォーマンス・コスト発生を避けるには、select-item フィールド名に SqlFieldName とまったく同じ大文字/小文字を使用するか、または列エイリアスを指定する必要があります。例えば、FamilyName AS FamilyName などの、大文字/小文字がまったく同じ列エイリアスを指定することが役立つ場合もあります。
select-item フィールドには、列エイリアスを指定できます。列エイリアスは、識別子の名前付け規約に従い、大文字/小文字の任意の組み合わせで指定でき、非英数字を含めることができます。列エイリアスは、大文字/小文字の任意の組み合わせで参照でき、Caché SQL は select-item フィールドに指定されている大文字/小文字に解決します。Caché は、定義されたフィールドに対応するプロパティのリストに突き合わせを試行する前に、列エイリアスのリストへの突き合わせを必ず試行します。列エイリアスを定義した場合、結果セット表示内のデータ列ヘッダ名は、フィールド名ではなく、指定した大文字/小文字の列エイリアスとなります。
SELECT クエリが正常に完了すると、Caché SQL はそのクエリの結果セット・クラスを生成します。結果セット・クラスには、選択した各フィールドに対応するプロパティが含まれます。SELECT クエリに重複フィールド名が含まれている場合、文字を追加することによって、クエリ内のフィールドの各インスタンスに対して一意のプロパティ名が生成されます。この理由から、1 個のクエリ内では 36 個のインスタンスを超える同じフィールドを含めることはできません。
クエリの生成された結果セット・クラスには、列エイリアスのプロパティも含まれます。大文字/小文字の解決のためのパフォーマンス・コスト発生を避けるには、列エイリアスを参照するときに、SELECT 文での列エイリアスの指定時に使用したものと同じ大文字/小文字を使用する必要があります。
ユーザ指定の列エイリアスに加え、Caché SQL はさらに、各フィールド名に最大で 3 つのエイリアス (フィールド名の共通大文字/小文字バリアントに対応するエイリアス) を自動的に生成します。生成されるエイリアスは、ユーザには表示されません。エイリアスによるプロパティへのアクセスは、文字変換による大文字/小文字の解決よりも高速であるという、パフォーマンス上の理由からこれは提供されます。例えば、SELECT が FAMILYNAME を指定しており、対応するプロパティが familyname である場合、Caché SQL は、生成されたエイリアスを使用して大文字/小文字を解決します (FAMILYNAME を familyname にします)。ただし、SELECT が fAmILyNaMe を指定しており、対応するプロパティが familyname である場合、Caché SQL は、低速な文字変換プロセスを用いて大文字/小文字を解決する必要があります。
select-item 項目は、式、集約関数、サブクエリ、ユーザ定義関数、アスタリスク、または他の何らかの値である場合もあります。フィールド名以外の select-item 項目の詳細は、SELECT コマンドのリファレンス・ページの、"select-item" セクションを参照してください。
JOIN 演算
JOIN は、テーブルのデータを別のテーブルのデータと結合する手段を提供し、レポートやクエリの定義に頻繁に使用されます。SQL では、JOIN は、2 つのテーブルからのデータを組み合わせて、制限条件に当てはまる 3 つ目のテーブルを作成する演算です。作成されたテーブルのすべての行は、制限条件を満たす必要があります。
Caché SQL は、CROSS JOIN、INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN、および FULL OUTER JOIN の 5 種類の結合 (一部は複数の構文形式) をサポートしています。外部結合は、条件式の全範囲の述語と論理演算子を使用する ON 節をサポートします。NATURAL 外部結合および USING 節を使用した外部結合は、部分的にサポートしています。これらの結合タイプの定義および詳細は、"Caché SQL リファレンス" の "JOIN" のページを参照してください。
クエリに結合が含まれている場合、そのクエリ内のすべてのフィールド参照には、追加されたテーブル・エイリアスが必要です。Caché はデータ列ヘッダ名にテーブル・エイリアスを組み込まないので、データのソースであるテーブルを明確にするために、select-item フィールドに列エイリアスを指定することもできます。
次の例では、結合操作を使用して、Sample.Person 内の "架空の" (ランダムに割り当てられた) 郵便番号を Sample.USZipCode 内の実際の郵便番号および都市名と照合しています。WHERE 節が指定されている理由は、USZipCode にはすべてのあり得る 5 桁の郵便番号が含まれているわけではないからです。
SELECT P.Home_City,P.Home_Zip AS FakeZip,Z.ZipCode,Z.City AS ZipCity,Z.State
FROM Sample.Person AS P LEFT OUTER JOIN Sample.USZipCode AS Z
ON P.Home_Zip=Z.ZipCode
WHERE Z.ZipCode IS NOT NULL
ORDER BY P.Home_City
多数のフィールドを選択するクエリ
クエリで 1,000 個を超える select-item フィールドを選択することはできません。
150 個を超える select-item フィールドを選択するクエリには、次のパフォーマンス上の考慮事項が存在する場合があります。つまり、Caché が結果セット列エイリアスを自動的に生成するということです。それらの生成されたエイリアスは、大文字/小文字のバリエーションを迅速に解決するためのユーザ定義エイリアスを持たないフィールド名に提供されます。エイリアスを使用する大文字/小文字解決は、文字変換による大文字/小文字解決よりもはるかに高速です。ただし、生成される結果セット列エイリアスの数は、500 までに制限されています。一般に Caché では、各フィールドに対して (大文字/小文字の最も一般的な 3 つのバリエーションに合わせて) これらのエイリアスが 3 つ生成されるので、クエリの先頭にある 150 個ほどの指定フィールドに対してエイリアスが生成されることになります。したがって、150 個より少ないフィールドを参照するクエリは、それよりもかなり多くのフィールドを参照するクエリと比較すると、結果セットのパフォーマンスは一般に良好ということになります。非常に大規模なクエリでは、select-item の各フィールドに対してまったく同じ列エイリアスを指定して (SELECT FamilyName AS FamilyName など)、列エイリアスで結果セット項目を参照するときに必ず同じ大文字/小文字が使用されるようにすることで、このパフォーマンスの問題を回避できます。
名前付きクエリの定義と実行
名前付きクエリは、以下に示すように定義および実行できます。
-
CREATE QUERY を使用してクエリを定義し、CALL を使用してそのクエリを実行します。
-
クラス内で Query キーワードを使用してクエリを定義します。
-
%SQL.StatementOpens in a new tab の %PrepareClassQuery() メソッドと %Execute() メソッドを使用してクラス・クエリを実行します。“ダイナミック SQL の使用法” を参照してください。
-
%Library.ResultSetOpens in a new tab の Execute() メソッドを使用してクラス・クエリを実行します。“従来の結果セット・クラスを使用した ダイナミック SQL” を参照してください。
-
CREATE QUERY と CALL
CREATE QUERY を使用してクエリを定義し、CALL を使用して、名前でそれを実行できます。以下の例では、1 つ目はクエリ AgeQuery を定義する SQL プログラムであり、2 つ目はそのクエリを実行するダイナミック SQL です。
CREATE QUERY Sample.AgeQuery(IN topnum INT DEFAULT 10,IN minage INT 20)
PROCEDURE
BEGIN
SELECT TOP :topnum Name,Age FROM Sample.Person
WHERE Age > :minage
ORDER BY Age ;
END
ZNSPACE "Samples"
SET mycall = "CALL Sample.AgeQuery(11,65)"
SET tStatement = ##class(%SQL.Statement).%New()
SET qStatus = tStatement.%Prepare(mycall)
IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET rset = tStatement.%Execute()
DO rset.%Display()
DROP QUERY Sample.AgeQuery
クラス・クエリ
クエリはクラス内で定義できます。多くの場合、そのクラスは %Persistent ですが、その他のクラスでもかまいません。クエリは、同じクラスで定義されたデータ、または同じネームスペースの別のクラスで定義されたデータを参照できます。以下に示すクラス定義の例では、クラス・クエリを定義しています。
Class Sample.QClass Extends %Persistent [DdlAllowed]
{
Query MyQ(Myval As %String) As %SQLQuery [SqlProc]
{
SELECT Name,Home_State FROM Sample.Person
WHERE Home_State = :Myval ORDER BY Name
}
}
以下に示す例では、前の例で Sample.QClass クラス内に定義した MyQ クエリを実行します。
SET Myval="NY"
SET stmt=##class(%SQL.Statement).%New()
SET status = stmt.%PrepareClassQuery("Sample.QClass","MyQ")
IF status'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(status) QUIT}
SET rset = stmt.%Execute(Myval)
DO rset.%Display()
WRITE !,"End of data"
以下のダイナミック SQL の例では、%SQL.StatementOpens in a new tab を使用して Sample.Person クラス内で定義されている ByName クエリを実行しています。このとき、文字列を渡すことで、その文字列値で始まる名前を返すように制限しています。
SET statemt=##class(%SQL.Statement).%New()
SET cqStatus=statemt.%PrepareClassQuery("Sample.Person","ByName")
IF cqStatus'=1 {WRITE "%PrepareClassQuery failed:" DO $System.Status.DisplayError(cqStatus) QUIT}
SET rs=statemt.%Execute("L")
DO rs.%Display()
詳細は、"Caché オブジェクトの使用法" の “クラス・クエリの定義と使用” を参照してください。
実行したクエリに自動的に割り当てられるクエリ名については、"Caché SQL 最適化ガイド" の "クエリ・キャッシュ" の章を参照してください。
ユーザ定義関数を呼び出すクエリ
Caché SQL では、SQL クエリでクラス・メソッドを実行できます。これにより、SQL の構文を拡張するための便利な機能が実現しました。
ユーザ定義の関数を作成するには、永続 Caché クラス内にクラス・メソッドを定義します。メソッドにはリテラル (非オブジェクト) の返り値が必要です。これは、クラス・メソッドである必要があります。SQL クエリでは、インスタンス・メソッドを呼び出すためのオブジェクト・インスタンスが作成されないためです。また、これは、SQL ストアド・プロシージャとして定義される必要があります。
例えば、MyApp.Person クラスで Cube() メソッドを定義できます。
Class MyApp.Person Extends %Persistent [DdlAllowed,language = basic]
{
/// Find the Cube of a number
ClassMethod Cube(val As %Integer) As %Integer [SqlProc]
{
Return val * val * val
}
}
CREATE FUNCTION 文、CREATE METHOD 文、または CREATE PROCEDURE 文を使用して、SQL 関数を作成できます。
SQL 関数を呼び出すには、SQL プロシージャの名前を指定します。SQL 関数は、SQL コード内でスカラ式を指定できる任意の場所から呼び出すことができます。関数名はそのスキーマ名で修飾できますが、無修飾でもかまいません。無修飾の関数名では、現在の既定のスキーマ名が使用されます。関数名は、区切り文字付き識別子とすることができます。
SQL 関数には、括弧で囲んだパラメータ・リストが必要です。パラメータ・リストは空でもかまいませんが、括弧は必ず記述します。指定したパラメータはすべて入力パラメータとして機能します。出力パラメータはありません。
SQL 関数は値を返す必要があります。
例えば、以下の SQL クエリは、ユーザ定義の SQL 関数を組み込み SQL 関数であるかのようにメソッドとして呼び出します。
SELECT %ID, Age, MyApp.Person_Cube(Age) FROM MyApp.Person
このクエリは Age のそれぞれの値に対し Cube() メソッドを呼び出し、返り値を結果に表示します。
SQL 関数は入れ子にして使用できます。
指定した関数が見つからない場合、Caché では SQLCODE -359 エラーが発行されます。指定した関数名が不明確である場合、Caché では SQLCODE -358 エラーが発行されます。
コレクション・プロパティ
既定ストレージ (%Library.CacheStorage) を使用してクラスから SQL に子テーブルとして投影されるコレクション・プロパティは、そのクラスによって投影されたテーブル内の 1 つの列としても投影されます。この列の値は、コレクションのシリアル化された値となります。この 1 つの列プロパティは、SQL のリスト・フィールドとして投影されます。
例えば、Sample.Person 内のコレクション列 Home は、列 Home_Street、Home_City、Home_State、および Home_Zip を含む子テーブルとして投影されます。以下の例では、これらの子テーブルの列から値が返されます。
SELECT TOP 4 Name,Home_Street,Home_City,Home_State,Home_Zip
FROM Sample.Person
以下の例では、同じ値が、リスト形式のデータを含む 1 つのコレクション列として返されます。
SELECT TOP 4 Name,$LISTTOSTRING(Home,'^')
FROM Sample.Person
既定では、この Home 列は列としては投影されません。
コレクションが子テーブルとして投影される場合は、$SYSTEM.SQL 構成メソッドである GetCollectionProjection()Opens in a new tab および SetCollectionProjection()Opens in a new tab を使用して、コレクションを 1 つの列として投影するかどうかを決定できます。このシステム全体に対する設定の変更は、クラスをコンパイルまたはリコンパイルしたときにクラスごとに反映されます。
フリー・テキスト検索を呼び出すクエリ
Caché では、以下のサポートを含む “フリー・テキスト検索” をサポートしています。
-
語幹解析
-
複数語による検索 (N-gram)
-
自動分類
-
ディクショナリの管理
この機能によって、フル・テキストによるインデックス機能を SQL でサポートできるほか、コレクションを子テーブルとして投影せずに、SQL を使用してコレクションの個々の要素のインデックスを作成して参照できます。コレクション・インデックス機能をサポートする基本メカニズムとフル・テキスト・インデックス機能をサポートする基本メカニズムは密接に関連していますが、テキスト取得には特別なプロパティが多数あるため、特別なクラスと SQL 機能が用意されています。
これらの機能をサポートする基本クラスの詳細は、"%Text.TextOpens in a new tab クラス" を参照してください。
SQL を使用したフル・テキスト・インデックス機能とテキスト取得機能
SQL でテキストのインデックス作成とテキスト・データの検索を実行するために、%Library.TextOpens in a new tab クラスと %TextOpens in a new tab パッケージが用意されています。既存の %StringOpens in a new tab プロパティでこの機能を使用するには、%StringOpens in a new tab を %TextOpens in a new tab に変更して、LANGUAGECLASS パラメータを設定します。英語テキストの場合は、宣言は以下のように指定します。
Property myNotes As %Text ( LANGUAGECLASS="%Text.English", MAXLEN=1000 );
Index myFullTextIndex On myNotes(KEYS);
LANGUAGECLASS は、テキスト・インデックス作成とテキスト検索が効率的に実行できるように、SQL とインデクサに必要なインタフェースを提供するヘルパー・クラスの名前を指定します。%TextOpens in a new tab プロパティには MAXLEN の値 (バイト単位) を指定する必要があります。
使用可能なテキスト対応述語は、%CONTAINS、%CONTAINSTERM、および %SIMILARITY です。
%TextOpens in a new tab プロパティを宣言してオプションでインデックスを作成した後は、以下のように SQL の %CONTAINS 述語を使用してフル・テキスト・クエリを発行できます。
SELECT plaintiff, legalBrief FROM transcript
WHERE plaintiff = 'John Doe' AND
legalBrief %CONTAINS ('neighbor', 'tree', 'roof')
上記クエリを使用すると、plaintiff が 'John Doe' で、用語 'neighbor'、'tree'、および 'roof' が legalBrief に含まれているトランスクリプトがすべて返されます。
Caché には、%TextOpens in a new tab パッケージ内に英語、スペイン語、フランス語、イタリア語、ドイツ語、日本語、ポルトガル語の言語固有のパーサが用意されています。これらは容易に使用できる一方で、言語固有のサブクラスを構成して高度な操作を実現できるようにもなっています。例えば、1 つの語から派生した語 (block、blocks、blocking など) を共通語幹にマップする語幹解析、複数語句 (N-gram) のサポート、不要語のフィルタ処理、(迷惑メールのフィルタ処理などに使用する) 自動テキスト分類などの機能があります。
完全な長さのクエリの N-gram をサポートするようにタイプ・クラスに設定していなくても、複数単語の文字列を %CONTAINS に指定できます。例えば、個別の単語のみが格納されるように %Text クラスを設定していても、次の述語を指定できます。
SELECT author FROM famousQuotations WHERE
quotetext %CONTAINS('eggs in one basket')
上記のクエリを使用すると、テキスト・クラスで 1 単語のみ (NGRAMLEN=1) を持つドキュメントを指定しても、指定語句を厳密に含む文書のすべての著者が返されます。このパターンが上記の場合のように N-gram の長さよりも長い場合は、SQL により "[" (含む) 演算子で行がフィルタ処理されます。"[" 演算子では大文字と小文字が区別されるため、NGRAMLEN よりも長いパターンでは、%CONTAINS 述語でも大文字と小文字が区別されます。その結果、次のように、NGRAMLEN によって返される行も変わります。
mission %CONTAINS('Fortune 5')
NGRAMLEN >= 2 の場合、'Fortune 5' を含む行のみが返されます。
NGRAMLEN < 2 の場合、'Fortune 5'、'Fortune 50'、'Fortune 500' などを含む行が返されます。これらのパターンはすべて "[" テストによる評価を満たすためです。
Text インタフェースの機能の詳細は、%Text.TextOpens in a new tab クラスおよびその言語固有のサブクラス (%Text.EnglishOpens in a new tab など) のマニュアルを参照してください。
SQL を使用したコレクション・インデックス機能とクエリ・コレクション機能
コレクションは、SQL の WHERE 節に FOR 節を使用して参照できます。以下はその例です。
FOR SOME %ELEMENT(collectionRef) [AS label] (predicate)
FOR SOME %ELEMENT 節は、STORAGEDEFAULT="list" を指定する配列およびリスト・コレクションに使用できます。predicate は、擬似列 %KEY または %VALUE、あるいはその両方への参照を 1 つ指定できます。以下に、FOR SOME %ELEMENT 節の使用方法の例をいくつか示します。次の例は、FavoriteColors に 'Red' がある人の名前と、それぞれの FavoriteColors のリストを返します。
SELECT Name,FavoriteColors FROM Sample.Person
WHERE FOR SOME %ELEMENT(FavoriteColors) (%Value = 'Red')
どの SQL 述語も %Value (または %Key) の後に記述できます。例えば、次の例も有効な構文となります。
SELECT Name,FavoriteColors FROM Sample.Person
WHERE FOR SOME %ELEMENT(Sample.Person.FavoriteColors)
(%Value IN ('Red', 'Blue', 'Green'))
リスト・コレクションは、1 から始まる連続数値のキーを持つ配列コレクションの特別な場合と見なされます。配列コレクションには、任意の NULL でないキーを指定できます。
FOR SOME (children) (%Key = 'betty' AND %Value > 5)
組み込みリストと配列コレクション・タイプのほか、任意のプロパティに BuildValueArray() クラス・メソッドを指定することで、汎用コレクションを作成することもできます。BuildValueArray() クラス・メソッドは、プロパティ値をローカル配列に変換します。ここで、配列の各添え字は %KEY、配列の値は対応する %VALUE になります。
%KEY または %VALUE の単純な選択のほか、以下の例のように 2 つのコレクションを論理的に結合することもできます。
FOR SOME %ELEMENT(flavors) AS f
(f.%VALUE IN ('Chocolate', 'Vanilla') AND
FOR SOME %ELEMENT(toppings) AS t
(t.%VALUE = 'Butterscotch' AND
f.%KEY = t.%KEY))
この例には、キーによって位置的に関連付けられた flavors と toppings という 2 つのコレクションがあります。このクエリでは、flavors の要素に指定した chocolate と vanilla の行が選択され、対応する toppings としてリストされた butterscotch によって行が絞り込まれ、%KEY によって対応関係が示された結果が作成されます。
使用上の注意と制限事項
-
FOR SOME %ELEMENT は、WHERE 節でのみ指定できます。
-
%CONTAINS は、WHERE 節でのみ指定できます。
-
%KEY または %VALUE、あるいはその両方は、FOR 述語でのみ指定できます。
-
特定の %KEY または %VALUE は、一度のみ参照できます。
-
%KEY および %VALUE は、外部結合には指定できません。
-
%KEY および %VALUE は、値式には指定できません (述語のみに指定できます)。
-
文字列の最大長を超えるストリームでは、%CONTAINS 述語ではなく %CONTAINSTERM 述語を使用する必要があります。文字列の最大長の詳細は、"Caché プログラミング入門ガイド" の “サーバ構成オプション” の章にある “長い文字列演算のサポート” のセクションを参照してください。
-
文字列の最大長を超えるストリームでは、インデックス・フィールドで %SIMILARITY のみを使用できます。文字列の最大長の詳細は、"Caché プログラミング入門ガイド" の “サーバ構成オプション” の章にある “長い文字列演算のサポート” のセクションを参照してください。
疑似フィールド変数
Caché の SQL クエリは、以下の疑似フィールド値をサポートしています。
-
%ID — 実際の RowId フィールドの名前に関係なく、RowId フィールドの値を返します。
-
%TABLENAME — FROM 節で指定された既存テーブルの修飾名を返します。この修飾テーブル名は、FROM 節で指定された大文字と小文字の組み合わせではなく、そのテーブルの定義時に使用された大文字と小文字の組み合わせに従って返されます。FROM 節で未修飾のテーブル名が指定された場合は、%TABLENAME は修飾テーブル名 (<スキーマ名>.<テーブル名>) を返し、このスキーマ名はシステム全体の既定のスキーマ名またはスキーマ検索パス (指定されている場合) から取得されます。例えば、FROM 節で mytable と指定されている場合は、%TABLENAME 変数は SQLUser.MyTable を返す可能性があります。
-
%CLASSNAME — FROM 節で指定された既存テーブルに対応する修飾クラス名 (<パッケージ名>.<クラス名>) を返します。例えば、FROM 節で SQLUser.mytable と指定されている場合は、%CLASSNAME 変数は User.MyTable を返す可能性があります。
疑似フィールド変数を返すことができるのは、データが含まれたテーブルについてのみです。
FROM 節で複数のテーブルが指定されている場合は、以下の例に示すように、テーブルのエイリアスを使用する必要があります。
&sql(SELECT P.Name,P.%ID,P.%TABLENAME,E.%TABLENAME
INTO :name,:rid,:ptname,:etname
FROM Sample.Person AS P,Sample.Employee AS E)
WRITE ptname," Name is: ",name,!
WRITE ptname," RowId is: ",rid,!
WRITE "1st TableName is: ",ptname,!
WRITE "2nd TableName is: ",etname,!
%TABLENAME 列と %CLASSNAME 列には、Literal_n という既定の列名が割り当てられます。ここで n は、SELECT 文内の疑似フィールド変数の select-item 位置です。
クエリ・メタデータ
ダイナミック SQL を使用すると、クエリ内で指定した列の数、クエリ内で指定した列の名前 (またはエイリアス)、クエリ内で指定した列のデータ型など、クエリに関するメタデータが返されます。
以下の ObjectScript のダイナミック SQL の例は、Sample.Person 内の全列の列名および列の ODBC データ型の整数コードを返します。
SET myquery="SELECT * FROM Sample.Person"
SET rset = ##class(%SQL.Statement).%New()
SET qStatus = rset.%Prepare(myquery)
IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET x=rset.%Metadata.columns.Count()
WHILE x>0 {
SET column=rset.%Metadata.columns.GetAt(x)
WRITE !,x," ",column.colName," ",column.ODBCType
SET x=x-1 }
WRITE !,"end of columns"
この例では、列は、列の順番とは逆にリストされます。ODBC では Caché list データ型値をコンマで区切られた値の文字列で表すので、リスト構造化されたデータが含まれている FavoriteColors 列は、データ型 12 (VARCHAR) を返します。
詳細は、このドキュメントの "ダイナミック SQL" の章、および "インターシステムズ・クラス・リファレンス" の %SQL.StatementOpens in a new tab クラスを参照してください。
クエリと ECP
エンタープライズ・キャッシュ・プロトコルを使用する Caché の実装ではクエリ結果を同期化することができます。ECP は分散データ・キャッシュ・アーキテクチャであり、異種のサーバ・システムで構成されるネットワークに分散されるデータとロックを管理します。
ECP の同期化がアクティブな場合、SELECT 文が実行されるたびに、Caché ではデータベース・サーバへの ECP 要求すべての保留が強制されます。これが完了すると、クライアント・キャッシュの同期が保証されます。この同期化はクエリの Open ロジックで行われます。これがカーソル・クエリである場合は、OPEN カーソル実行となります。
管理ポータルを使用して、ECP の同期化を確立することができます。管理ポータルに移動します。[システム管理] から、[構成]、[SQL およびオブジェクトの設定]、[一般SQL設定] (システム, 構成, 一般SQL設定) を選択します。この画面で、[SQL SELECT Synchronizes ECP Cache] の現在の設定を表示して変更できます。既定値は、“No” (ECP 同期化は実行されない) です。これはシステム全体の設定となります。この設定の変更は、即座にシステム上の Caché 処理すべてに作用します。
詳細は、"Caché 分散データ管理ガイド" を参照してください。