Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

埋め込み SQL の使用法

InterSystems IRIS® データ・プラットフォームで使用される ObjectScript コード内に SQL 文を埋め込むことができます。これらの埋め込み SQL 文は、実行時に最適化された実行可能なコードに変換されます。

埋め込み SQL には以下の 2 種類があります。

  • 単純な埋め込み SQL クエリは、1 つの行の値のみを返すことができます。また、単純な埋め込み SQL は、単一行を対象とする挿入、更新、および削除や、その他の SQL 操作にも使用できます。

  • カーソル・ベースの埋め込み SQL クエリは、クエリ結果セットの繰り返し処理を行って、複数の行の値を返すことができます。また、カーソル・ベースの埋め込み SQL は、複数行を対象とする更新および削除の SQL 操作にも使用できます。

Note:

埋め込み SQL は、ターミナルのコマンド行に入力することも、XECUTE 文で指定することもできません。コマンド行から SQL を実行するには、$SYSTEM.SQL.Execute()Opens in a new tab メソッドまたは SQL シェル・インタフェースを使用します。

埋め込み SQL のコンパイル

埋め込み SQL は、これを含むルーチンのコンパイル時にはコンパイルされません。埋め込み SQL のコンパイルは、SQL コードの最初の実行時 (ランタイム) に行われます。最初の実行によって、実行可能なクエリ・キャッシュが定義されます。これはダイナミック SQL のコンパイルと似ています。この際、SQL 準備処理が実行されるまで SQL コードはコンパイルされません。

埋め込み SQL コードは、ルーチンの初回実行まで、SQL テーブルおよび他のエンティティに対して検証されません。このため、ルーチンのコンパイル時に存在しないテーブルまたはその他の SQL エンティティを参照する埋め込み SQL を含む、ルーチンまたは永続クラスのメソッドをコンパイルすることができます。この理由により、ほとんどの SQL エラーはコンパイル時ではなく実行時に返されます。

ルーチンのコンパイル時に、埋め込み SQL に対して SQL 構文チェックが実行されます。埋め込み SQL に無効な SQL 構文があった場合、ObjectScript コンパイラが失敗し、コンパイル・エラーが生成されます。

管理ポータルの SQL インタフェースを使用して、SQL コードを実行することなく、埋め込み SQL で指定された SQL エンティティの存在をテストすることができます。これについては、"埋め込み SQL コードの検証" で説明します。埋め込み SQL コードの検証では、SQL 構文の検証と SQL エンティティの存在チェックの両方が行われます。"埋め込み SQL コードの検証" に説明されているように、/compileembedded=1 修飾子を使用して埋め込み SQL コードを含むルーチンをコンパイルすることで、ランタイム実行の前に 埋め込み SQL コードを検証することを選択できます。

埋め込み SQL 文が正常に実行されると、クエリ・キャッシュが生成されます。その埋め込み SQL の以降の実行では、埋め込み SQL ソースをリコンパイルする代わりに、クエリ・キャッシュが使用されます。これにより、クエリ・キャッシュのパフォーマンス上のメリットが埋め込み SQL にもたらされます。これらのクエリ・キャッシュは、各テーブルの管理ポータルで [カタログの詳細] の [クエリキャッシュ] リストに表示されます。

カーソル・ベースの埋め込み SQL 文のランタイム実行は、OPEN コマンドを使用して初めてカーソルを開くときに行われます。管理ポータルの [SQL 文] リストに示されているように、実行のこの時点で、最適化されたクエリ・キャッシュ・プランが生成されます。[SQL 文] リストに表示される [場所] は、埋め込み SQL コードを含むルーチンの名前です。埋め込み SQL を実行しても、[クエリキャッシュ] リストにエントリは生成されません。%sqlcq.USER.cls1 などのクラス名を持つこれらのリストは、ダイナミック SQL クエリによって作成されます。

Note:

InterSystems IRIS の旧バージョンで使用されていた #sqlcompile mode プリプロセッサ文は非推奨になりました。解析はされますが、ほとんどの埋め込み SQL コマンドに対して処理は行いません。ほとんどの埋め込み SQL コマンドは、#sqlcompile mode の設定に関係なく、実行時にコンパイルされます。ただし、少数の埋め込み SQL コマンドでは、#sqlcompile mode=deferred に設定することに引き続き意味があります。すべてのタイプの埋め込み SQL コマンドが実行時に強制的にコンパイルされるようになるからです。

埋め込み SQL とマクロ・プリプロセッサ

埋め込み SQL は、メソッド内およびトリガ内 (ObjectScript を使用するように定義されている場合)、または ObjectScript の MAC ルーチン内で使用できます。MAC ルーチンは InterSystems IRIS マクロ・プリプロセッサによって処理され、INT (中間) コードに変換された後、実行可能な OBJ コードにコンパイルされます。これらの処理は、埋め込み SQL コード自体のコンパイル時ではなく、埋め込み SQL を含むルーチンのコンパイル時に実行されます。埋め込み SQL コードは実行時までコンパイルされません。詳細は、"ObjectScript の使用法" の "ObjectScript マクロとマクロ・プリプロセッサ" の章を参照してください。

埋め込み SQL 文自体に InterSystems IRIS マクロ・プリプロセッサ文 (# コマンド、## 関数、または $$$ マクロ参照) が含まれる場合、これらの文はルーチンがコンパイルされ、実行時に SQL コードで使用できるようになったときにコンパイルされます。これにより、ObjectScript コード本文を含む CREATE PROCEDURECREATE FUNCTIONCREATE METHODCREATE QUERYCREATE TRIGGER のいずれかの文が影響を受ける可能性があります。

埋め込み SQL のインクルード・ファイル

埋め込み SQL 文では、参照するマクロ・インクルード・ファイルを、実行時にシステムにロードする必要があります。

埋め込み SQL のコンパイルは最初の参照まで延期されるため、埋め込み SQL クラスがコンパイルされるコンテキストは、埋め込み SQL を含むクラスやルーチンのコンパイル時環境ではなく、実行時環境になります。実行時現在のネームスペースが、埋め込み SQL を含むルーチンのコンパイル時のネームスペースと異なる場合、コンパイル時のネームスペースのインクルード・ファイルは実行時のネームスペースに表示されないことがあります。この場合、以下が発生します。

  1. インクルード・ファイルが実行時のネームスペースに表示されない場合、埋め込み SQL のコンパイルですべてのインクルード・ファイルが削除されます。SQL コンパイルでインクルード・ファイルが必要になることはめったにないため、実行時の埋め込み SQL のコンパイルは多くの場合、インクルード・ファイルなしでも成功します。

  2. インクルード・ファイルの削除後にコンパイルに失敗した場合、InterSystems IRIS エラーでルーチンのコンパイル時のネームスペース、埋め込み SQL の実行時のネームスペース、および実行時のネームスペースで表示されないインクルード・ファイルのリストが報告されます。

#SQLCompile マクロ指示文

マクロ・プリプロセッサには、埋め込み SQL で使用するための 3 つのプリプロセッサ指示文が用意されています。

  • #sqlcompile select は、SELECT 文から返されたときのデータ表示の形式を指定します。また、INSERT 文または UPDATE 文、あるいは SELECT 入力ホスト変数に指定した場合はデータ入力の必須形式を指定します。Logical (既定)、DisplayODBCRuntimeText (Display と同義)、および FDBMS (下記参照) の 6 つのオプションがサポートされています。#sqlcompile select=Runtime の場合、$SYSTEM.SQL.Util.SetOption("SelectMode",n)Opens in a new tab メソッドを使用してデータの表示方法を変更できます。n 値には、0 = 論理、1 = ODBC、または 2 = 表示を指定できます。

    #sqlcompile select オプションの指定に関係なく、INSERT または UPDATE は、保存のために、指定されたデータの値を対応する論理形式に自動的に変換します。

    #sqlcompile select オプションの指定に関係なく、SELECT は、述語の照合のために、入力ホスト変数の値を対応する論理形式に自動的に変換します。

    以下の各例では、クエリの表示に #sqlcompile select を使用する方法を示します。これらの例は、DOB (誕生日) 値を表示してから、SelectMode を ODBC 形式に変更し、再び DOB を表示します。最初の例では、SelectMode を変更しても表示には影響しません。2 番目の例では、#sqlcompile select=Runtime であるため、SelectMode を変更すると表示が変更されます。

       #sqlcompile select=Display
       &sql(SELECT DOB INTO :a FROM Sample.Person)
          IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
          ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
       WRITE "1st date of birth is ",a,!
       DO $SYSTEM.SQL.Util.SetOption("SelectMode",1)
       WRITE "changed select mode to: ",$SYSTEM.SQL.Util.GetOption("SelectMode"),!
       &sql(SELECT DOB INTO :b FROM Sample.Person)
       WRITE "2nd date of birth is ",b
       #sqlcompile select=Runtime
       &sql(SELECT DOB INTO :a FROM Sample.Person)
          IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
          ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
       WRITE "1st date of birth is ",a,!
       DO $SYSTEM.SQL.Util.SetOption("SelectMode",1)
       WRITE "changed select mode to: ",$SYSTEM.SQL.Util.GetOption("SelectMode"),!
       &sql(SELECT DOB INTO :b FROM Sample.Person)
       WRITE "2nd date of birth is ",b

    SelectMode オプションの詳細は、このドキュメントの “InterSystems IRIS SQL の基礎” の章にある “データ表示オプション” を参照してください。

    • #sqlcompile select=FDBMS は、埋め込み SQL で FDBMS と同様にデータをフォーマットできるようにするために用意されています。クエリの WHERE 節に定数値がある場合、FDBMS モードでは、それは Display 値であると見なされ、DisplayToLogical 変換を使用して変換されます。クエリの WHERE 節に変数がある場合は、FDBMS モードでは、FDBMSToLogical 変換を使用してそれが変換されます。FDBMSToLogical 変換メソッドは、Internal、Internal_$c(1)_External、および $c(1)_External という 3 つの FDBMS 変数形式を処理するように設計されている必要があります。 クエリで選択して変数に格納する場合は、それによって LogicalToFDBMS 変換メソッドが呼び出されます。このメソッドでは、Internal_$c(1)_External が返されます。

  • #sqlcompile path (または #import) は、データ管理コマンド (SELECTCALLINSERTUPDATEDELETETRUNCATE TABLE など) 内の未修飾テーブル名、ビュー名、およびストアド・プロシージャ名を解決するために使用されるスキーマ検索パスを指定します。スキーマ検索パスを指定しない場合、または指定されたスキーマ内にテーブルが見つからない場合、InterSystems IRIS は、既定のスキーマを使用します。#sqlcompile path および #import は、データ定義文 (ALTER TABLEDROP VIEWCREATE INDEXCREATE TRIGGER など) では無視されます。データ定義文では、未修飾名の解決には既定のスキーマが使用されます。

  • #sqlcompile audit は、埋め込み SQL 文の実行をシステム・イベント監査ログに書き込む必要があるかどうかを指定するブーリアン・スイッチです。詳細は、"埋め込み SQL の監査" を参照してください。

これらのプリプロセッサ指示文の詳細は、"ObjectScript の使用法" の "システム・プリプロセッサ・コマンド・リファレンス" のセクションを参照してください。

埋め込み SQL の構文

埋め込み SQL 指示文の構文を以下に示します。

&sql 指示文

埋め込み SQL 文は、以下の例に示すように、&sql() 指示文により、他のコードから区別されています。

   NEW SQLCODE,a
   WRITE "Invoking Embedded SQL",!
   &sql(SELECT Name INTO :a FROM Sample.Person)
      IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
      ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
   WRITE "The name is ",a

結果は、1 つ以上のホスト変数を指定する INTO 節を使用して返されます。この場合、ホスト変数には :a という名前が付けられています。詳細は、この章の “ホスト変数” のセクションを参照してください。ここには、SQLCODE とホスト変数との間のやりとりについての説明があります。

&sql 指示文は大文字と小文字を区別しないため、&sql、&SQL、&Sql などを使用できます。&sql 指示文の直後には、開始の括弧が続く必要があります (間にスペース、改行、またはコメントは使用できません)。&sql 指示文は、以下の例のように、ラベルと同じ行で使用することができます。

Mylabel  &sql(
       SELECT Name INTO :a 
       FROM Sample.Person
       )

&sql 指示文は、括弧で囲まれた有効な埋め込み SQL 文を含む必要があります。SQL 文は、自由にフォーマットして利用できますが、SQL では、空白と新規の行は無視されます。スタジオは、&sql 指示文を認識し、SQL 認識カラー表示機能を使用して SQL コードの文をカラー表示します。

マクロ・プリプロセッサが &sql 指示文を検出すると、SQL クエリ・プロセッサに引用符付きの SQL 文を渡します。クエリ・プロセッサは、クエリの実行に必要なコードを (ObjectScript の INT 形式で) 返します。その後、マクロ・プリプロセッサは &sql 指示文をこのコード (あるいは、コードを含むラベルへの呼び出し) に置換します。スタジオでは、クラスまたはルーチン用に作成された INT コードを調べることで、生成されたコードを表示できます ([表示] メニューの [他のコードを表示] オプションを使用します)。

&sql 指示文に無効な埋め込み SQL 文が含まれる場合、マクロ・プリプロセッサはコンパイル・エラーを生成します。無効な SQL 文には、構文エラーがある場合や、コンパイル時に存在しないテーブルや列を参照している場合があります。"埋め込み SQL コードの検証" を参照してください。

&sql 指示文には、括弧内の任意の場所に SQL スタイルのコメントを含めることができ、SQL コードが含まれない場合やコメント文のみが含まれる場合もあります。&sql 指示文に、SQL コードが含まれておらず、コメント文のみが含まれている場合、その指示文は空命令として解析され、SQLCODE 変数は定義されません。

  NEW SQLCODE
  WRITE !,"Entering Embedded SQL"
  &sql()
  WRITE !,"Leaving Embedded SQL"
  NEW SQLCODE
  WRITE !,"Entering Embedded SQL"
  &sql(/* SELECT Name INTO :a FROM Sample.Person */)
  WRITE !,"Leaving Embedded SQL"

&sql の代替構文

複雑な埋め込み SQL プログラムには、複数の &sql 指示文 (入れ子になった &sql 指示文など) が含まれることがあるため、以下の代替構文形式が用意されています。

  • ##sql(...) : この指示文は、機能面では &sql と等価です。コードをわかりやすくするために代替構文が用意されています。ただし、マーカ構文を含めることはできません。

  • &sql<marker>(...)<reversemarker> : この指示文を使用すると、複数の &sql 指示文を、それぞれユーザが選択したマーカ文字またはマーカ文字列で特定して指定できます。このマーカ構文については、以下のセクションで説明します。

&sql のマーカ構文

具体的な &sql 指示文を、ユーザ定義のマーカ構文を使用して特定できます。この構文は、“&sql” と開始の括弧文字の間に指定された文字または文字列で構成されます。また、埋め込み SQL の最後には、閉じ括弧の直後にこのマーカと同じ文字を逆の順序で指定する必要があります。構文は、以下のとおりです。

  &sql<marker>( SQL statement )<reverse-marker>

空白 (スペース、タブ、または改行) は、&sql、marker、および開始の括弧の間、あるいは閉じ括弧と reverse-marker の間には使用できません。

marker には、1 文字または一連の文字を指定できます。また、marker には、以下の句読点文字を含めることはできません。

( + - / \ | * )

marker には、空白 (スペース、タブ、または改行) を含めることはできません。その他すべての印刷可能文字や文字の組み合わせ (Unicode 文字など) を含めることができます。marker および reverse-marker では、大文字と小文字が区別されます。

対応する reverse-marker には、marker と同じ文字を逆の順序で指定する必要があります。例えば、以下のようになります。&sqlABC( ...)CBAmarker に [ や { を含める場合は、対応する ] や } を reverse-marker に含める必要があります。以下は、有効な &sql marker および reverse-marker の組み合わせの例です。

  &sql@@( ... )@@   &sql[( ... )]   &sqltest( ... )tset   &sql[Aa{( ... )}aA]

マーカの文字または文字列を選択する際には、次の重要な SQL の制限に注意してください。SQL コードでは、リテラル文字列やコメントを含めて、コードのどこにも “)<reversemarker>” を含めることはできません。例えば、マーカが “ABC“ だとすると、文字列 “)CBA“ は、埋め込み SQL コードのどこにも指定することはできません。指定した場合、有効なマーカと有効な SQL コードの組み合わせが原因となって、コンパイルが失敗します。したがって、marker の文字または文字列は、競合が起こらないように注意して選択することが重要です。

埋め込み SQL と行オフセット

埋め込み SQL が存在することで、ObjectScript の行オフセットは以下のような影響を受けます。

  • 埋め込み SQL は、その時点でのルーチンの INT コード行の総数に (少なくとも) 2 を追加します。そのため、1 行の埋め込み SQL は 3 行としてカウントされ、2 行の埋め込み SQL は 4 行としてカウントされます (それ以降も同様にカウントされます)。他のコードを呼び出す埋め込み SQL は、INT コードにさらに多くの行数を追加する可能性があります。

    コメントのみを含むダミーの埋め込み SQL 文 (例 : &sql( /* for future use */)) は、2 INT コード行としてカウントされます。

  • 埋め込み SQL に含まれるすべての行は、コメント行と空白行を含めて、行オフセットとしてカウントされます。

INT コード行は、^ROUTINE グローバルを使用して表示できます。

埋め込み SQL のコード

埋め込み SQL で SQL コードを記述する際には、以下の点を考慮してください。

埋め込み SQL からデータ値をエクスポートするために使用されるホスト変数については、この章の後半で説明します。

単純な SQL 文

単純な SQL 文 (1 つの埋め込み SQL 文) を使用して、以下のようなさまざまな演算を実行できます。

単純な SQL 文は、非カーソル・ベース SQL 文とも呼ばれます。カーソル・ベース埋め込み SQL については、この章で後述します。

例えば、以下の文は、ID 番号が 43 の Patient の名前のみを検索します。

 &sql(SELECT Name INTO :name
    FROM Patient
    WHERE %ID = 43)

複数の行を返すことのできる、クエリの単純文を使用する場合、最初の行のみが返されます。

 &sql(SELECT Name INTO :name
    FROM Patient
    WHERE Age = 43)

クエリによっては、実際にどの行が最初に返されるかの保証はありません。

埋め込み SQL のコンパイル時に、INTO 節の出力ホスト変数は NULL 文字列に設定されます。このため、単純な埋め込み SQL 文は、出力ホスト変数にアクセスする前に、SQLCODE=100 (クエリからデータが返されない)、または SQLCODE=0 (正常実行) をテストする必要があります。

スキーマ・ネームの解析

テーブル名、ビュー名、またはストアド・プロシージャ名は、修飾されている (スキーマ名を指定) か、未修飾 (スキーマ名の指定なし) かのいずれかです。名前がスキーマ名を指定しない場合、InterSystems IRIS はスキーマ名を以下のように解決します。

  • データ定義 : 未修飾名の解決にはシステム全体の既定のスキーマが使用されます。この既定のスキーマが存在しない場合、スキーマおよび対応するクラス・パッケージが InterSystems IRIS によって作成されます。すべてのデータ定義文でシステム全体の既定のスキーマが使用されます。データ定義文では、#import および #sqlcompile path マクロ・プリプロセッサ指示文は無視されます。

  • データ管理 : 埋め込み SQL 文を含むクラスまたはルーチンに対して有効な #sqlcompile path および #import マクロ・プリプロセッサ指示文のいずれかまたは両方によって指定されたスキーマ検索パスが使用されます。#import および #sqlcompile path 指示文は、異なる機能を持つ使用可能なスキーマ名の互いに独立したリストです。どちらかまたは両方を使用して、未修飾のテーブル、ビュー、またはストアド・プロシージャ名にスキーマ名を指定できます。スキーマ検索パスが指定されていない場合、InterSystems IRIS はシステム全体の既定のスキーマ名を使用します。

スキーマの詳細は、"クラスの定義と使用" の “パッケージ” の章を参照してください。

リテラル値

埋め込み SQL クエリには、リテラル値 (文字列、数字、日付) が含まれる場合があります。文字列は一重引用符 (') で囲む必要があります。(InterSystems SQL では、二重引用符は区切り識別子を指定します。)

  &sql(SELECT 'Employee (' || Name || ')' INTO :name 
       FROM Sample.Employee)
          IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
          ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
  WRITE name

数値は (引用符で囲まずに) 直接使用できます。リテラルの数値およびタイムスタンプ値には、InterSystems IRIS がこれらのリテラル値をフィールド値と比較する前に、“簡略な正規化“ が行われます。以下の例では、+0050.000 は 50 に正規化されます。

  &sql(SELECT Name,Age INTO :name,:age 
       FROM Sample.Person
       WHERE Age = +0050.000)
         IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
         ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
  WRITE name," age=",age

算術、関数、および特殊変数式は、以下のように指定できます。

  &sql(DECLARE C1 CURSOR FOR 
       SELECT Name,Age-65,$HOROLOG INTO :name,:retire,:today 
       FROM Sample.Person
       WHERE Age > 60
       ORDER BY Age,Name)
  &sql(OPEN C1)
      QUIT:(SQLCODE'=0)
  &sql(FETCH C1)
  WHILE (SQLCODE = 0) {
     WRITE $ZDATE(today)," ",name," has ",retire," eligibility years",!
    &sql(FETCH C1) }
  &sql(CLOSE C1)

また、リテラル値は、入力ホスト変数を使用して入力することもできます。入力ホスト数値にも、“簡略な正規化“ が行われます。詳細は、この章の “ホスト変数” セクションを参照してください。

埋め込み SQL では、## で始まるいくつかの文字シーケンスは文字列リテラル内での使用が許可されず、##lit を使用して指定する必要があります。この文字シーケンスは、##;##beginlit##expression(##function(##quote(##stripq(、および ##unique( です。例えば、以下の例は失敗します。

  WRITE "Embedded SQL test",!
  &sql(SELECT 'the sequence ##unique( is restricted' INTO :x)
  WRITE x

以下の回避策は成功します。

  WRITE "Embedded SQL test",!
  &sql(SELECT 'the sequence ##lit(##unique() is restricted' INTO :x)
  WRITE x

データ形式

埋め込み SQL では、データ値は “論理モード”、つまり SQL クエリ・プロセッサによって使用されるネイティブ形式の値です。LogicalToODBC 変換も LogicalToDisplay 変換も定義されていない文字列、整数やその他のデータ型に対しては何の影響も与えません。データ形式は %ListOpens in a new tab データ、および %DateOpens in a new tab%TimeOpens in a new tab データ型に影響します。

%List データ型は、出力不能なリスト・エンコーディング文字で開始する要素値として論理モードで表示されます。WRITE コマンドは、これらの値を連結された要素として表示します。例えば、Sample.Person の FavoriteColors フィールドには、$LISTBUILD('Red','Black') のように %List データ型が含まれます。埋め込み SQL の場合、これは論理モードでは 12 文字の長さの RedBlack として表示されます。表示モードでは、Red Black として表示されます。ODBC モードでは、Red,Black となります。詳細は、以下の例を参照してください。

  &sql(DECLARE C1 CURSOR FOR
       SELECT TOP 10 FavoriteColors INTO :colors
       FROM Sample.Person WHERE FavoriteColors IS NOT NULL)
  &sql(OPEN C1)
      QUIT:(SQLCODE'=0)
  &sql(FETCH C1)
  WHILE (SQLCODE = 0) {
     WRITE $LENGTH(colors),": ",colors,!
    &sql(FETCH C1) }
  &sql(CLOSE C1)

InterSystems IRIS の %DateOpens in a new tab および %TimeOpens in a new tab データ型は、論理形式として InterSystems IRIS の内部日付表示 ($HOROLOG 形式) を使用します。%DateOpens in a new tab データ型は、論理モードでは INTEGER 型、表示モードでは VARCHAR データ型、ODBC モードでは DATE データ型を返します。%TimeStampOpens in a new tab データ型は、論理、表示、および ODBC 形式に対して、ODBC 日付形式 (YYYY-MM-DD HH:MM:SS) を使用します。

例えば、以下のクラス定義について考えてみます。

Class MyApp.Patient Extends %Persistent
{
/// Patient name
Property Name As %String(MAXLEN = 50);

/// Date of birth
Property DOB As %Date;

/// Date and time of last visit
Property LastVisit As %TimeStamp;
}

このテーブルに対する単純な SQL クエリは、論理モードで値を返します。例えば、以下のクエリを考えてみます。

 &sql(SELECT Name, DOB, LastVisit
        INTO :name, :dob, :visit
         FROM Patient
        WHERE %ID = :id)

このクエリは、ホスト変数の namedob、および visit の 3 つのプロパティに対する論理値を返します。

ホスト変数
name "Weiss,Blanche"
dob 44051
visit "2001-03-15 11:11:00"

dob は、$HOROLOG 形式で表されています。$ZDATETIME 関数を使用して、これを表示形式に変換できます。

 SET dob = 44051
 WRITE $ZDT(dob,3),!

WHERE 節でも、同様です。例えば、任意の誕生日の Patient (患者) を検索するには、WHERE 節の論理値を使用します。

 &sql(SELECT Name INTO :name
        FROM Patient
        WHERE DOB = 43023)

または、ホスト変数を使用します。

 SET dob = $ZDH("01/02/1999",1)

 &sql(SELECT Name INTO :name
        FROM Patient
        WHERE DOB = :dob)

この場合、$ZDATEH 関数を使用して、表示形式の日付を論理 $HOROLOG 対応に変換します。

特権チェック

埋め込み SQL は、SQL 特権チェックを実行しません。特権の割り当てに関係なく、すべてのテーブル、ビュー、列にアクセスして、どんな操作でも実行できます。これは、埋め込み SQL を使用するアプリケーションが、埋め込み SQL 文を使用する前に特権を確認していると見なされるためです。

埋め込み SQLで InterSystems SQL の %CHECKPRIV 文を使用して、現在の特権を確認できます。

詳細は、このドキュメントの "SQL のユーザ、ロール、および特権" の章を参照してください。

ホスト変数

ホスト変数は、埋め込み SQL との間でリテラル値を受け渡しするローカル変数です。一般に、ホスト変数は、ローカル変数の値を埋め込み SQL への入力値として渡したり、SQL クエリ結果の値を埋め込み SQL クエリからの出力ホスト変数として渡すために使用されます。

ホスト変数を、スキーマ名、テーブル名、フィールド名、カーソル名などの SQL 識別子を指定するために使用することはできません。ホスト変数を、SQL キーワードを指定するために使用することはできません。

  • 出力ホスト変数は、埋め込み SQL でのみ使用されます。出力ホスト変数は INTO 節で指定されます。これは、埋め込み SQL でのみサポートされる SQL クエリの節です。埋め込み SQL をコンパイルすると、すべての INTO 節の変数が NULL 文字列 ('') に初期化されます。

  • 入力ホスト変数は、埋め込み SQL またはダイナミック SQL のどちらでも使用できます。ダイナミック SQL では、"?" 入力パラメータを使用してリテラルを SQL 文に入力することもできます。この “?” 構文は、埋め込み SQL では使用できません。

埋め込み SQL 内では、入力ホスト変数は、リテラル値を使用できる任意の場所で使用できます。出力ホスト変数は、SELECT 文または FETCH 文の INTO 節を使用して指定されます。

Note:

SQL の NULL が ObjectScript に出力された場合、その SQL の NULL は、ObjectScript の空文字列 ("")、つまり長さゼロの文字列で表されます。"NULL および未定義ホスト変数" を参照してください。

変数またはプロパティ参照をホスト変数として使用するには、その前にコロン (:) を付けます。埋め込み InterSystems SQL 内のホスト変数は以下のいずれかにできます。

  • ObjectScript の 1 つ以上のローカル変数 (:myvar など)。コンマ区切りのリストとして指定されます。ローカル変数は整形可能で、添え字を含めることができます。すべてのローカル変数と同様、大文字と小文字が区別され、Unicode 文字を含めることができます。

  • ObjectScript の 1 つのローカル変数配列 (:myvars() など)。ローカル変数配列は、1 つのテーブル (結合テーブルやビューではない) からのフィールド値のみを受け取ることができます。詳細は、後述の “列番号を添え字とするホスト変数” を参照してください。

  • :oref.Prop などのオブジェクト参照。Prop はプロパティ名であり、先頭に % 文字を使用してもしなくてもかまいません。これは、単純なプロパティでも多次元配列プロパティでもかまいません (oref.Prop(1) など)。:i%Prop や :i%%Data などのインスタンス変数として指定することができます。プロパティ名は、:Person."Home City" のように区切ることができます。区切られたプロパティ名は、区切り識別子のサポートが非アクティブ化されている場合でも使用できます。多次元プロパティには、:i%Prop() や :m%Prop() などのホスト変数参照を含めることができます。オブジェクト参照ホスト変数には、:Person.Address.City のような任意のレベル数のドット構文を含めることができます。

    oref.Prop がプロシージャ・ブロック・メソッドの中でホスト変数として使用される場合、oref.Prop 参照全体ではなく oref 変数が自動的に PublicList に追加され、NEW が実行されます。

ホスト変数内の二重引用符は、区切り識別子ではなくリテラル文字列を指定します (:request.GetValueAt("PID:SetIDPID"):request.GetValueAt("PID:PatientName(1).FamilyName") など)。

ホスト変数は、ObjectScript プロシージャの PublicList 変数リストにリストし、NEW コマンドを使用して再初期化する必要があります。埋め込み SQL で使用されるすべてのホスト変数をコメント文内にもリストするように InterSystems IRIS を構成できます。これについては、"InterSystems SQL の使用法" の "コメント" のセクションを参照してください。

ホスト変数の値は、以下のように動作します。

  • 入力ホスト変数は、SQL 文コードで変更されることはありません。埋め込み SQL を実行した後でも、その元の値が保持されます。ただし、入力ホスト変数の値には、SQL 文コードに提供される前に “簡略な正規化“ が行われます。つまり、有効な数値から、先頭と末尾にあるゼロ、先頭にある単一の + 記号、および末尾にある小数点が取り除かれます。タイムスタンプ値からは、末尾にあるスペース、秒の小数部の末尾にあるゼロ、および (秒の小数部がない場合は) 末尾にある小数点が取り除かれます。

  • INTO 節で指定される出力ホスト変数は、クエリのコンパイル時に定義されます。参照しても <UNDEFINED> エラーが発生しないように、NULL 文字列に設定されます。SQLCODE=0 の場合、ホスト変数の値は実際の値のみを表します。DECLARE ... SELECT ...INTO 文では、INTO 節の出力ホスト変数を、2 つの FETCH 呼び出し間で変更しないでください。変更すると、クエリが予期せぬ結果となる可能性があります。

出力ホスト変数を処理する前に、SQLCODE 値をチェックする必要があります。出力ホスト変数値は、SQLCODE=0 の場合にのみ使用してください。

ホスト変数のコンマ区切りリストを INTO 節で使用する場合は、select-items (フィールド、集約関数、スカラ関数、算術式、リテラル) の数と同じ数のホスト変数を指定する必要があります。ホスト変数の数が多すぎたり少なすぎたりすると、コンパイル時に SQLCODE -76 というカーディナリティ・エラーが発生します。

このことが一般に問題となるのは、埋め込み SQL で SELECT * を使用している場合です。例えば、SELECT * FROM Sample.Person が有効となるのは、コンマ区切りリストのホスト変数の数が 15 の場合のみです (15 は非表示でない列の正確な数であり、この数には、テーブル定義に応じて、システムによって生成される RowID (ID) 列が含まれる場合と含まれない場合があります)。この列の数は、"インターシステムズ・クラス・リファレンス" に記載されているプロパティの数と単純に一致するわけではない場合もあることに注意してください。

列数は変化する可能性があるため、個別のホスト変数の INTO 節リストと共に SELECT * を指定することは通常は推奨されません。SELECT * を使用している場合は、通常、以下に示すようなホスト変数の添え字付き配列の使用が推奨されます。

   NEW SQLCODE
  &sql(SELECT %ID,* INTO :tflds() FROM Sample.Person )
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
   FOR i=0:1:25 { 
       IF $DATA(tflds(i)) {
       WRITE "field ",i," = ",tflds(i),! }
     }

この例では、RowID が非表示であるかどうかに関係なく、%ID を使用して RowID をフィールド番号 1 として返します。この例では、フィールド番号の添え字は連続的なシーケンスではないことに注目してください。すなわち、一部のフィールドは非表示になっており、スキップされます。NULL を含むフィールドは、空の文字列値でリストされます。ホスト変数配列の使用法は、後述の “列番号を添え字とするホスト変数” を参照してください。

埋め込み SQL を終了するときに SQLCODE 値を直ちにチェックできるので、プログラミングをするうえで便利です。出力ホスト変数値は、SQLCODE=0 の場合にのみ使用してください。

ホスト変数の例

以下の ObjectScript の例では、埋め込み SQL 文は、出力ホスト変数を使用して、名前と自宅住所を SQL クエリから ObjectScript に返します。

   &sql(SELECT Name,Home_State
        INTO :CName,:CAddr
        FROM Sample.Person)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
      WRITE !,"Name is: ",CName
      WRITE !,"State is: ",CAddr

この埋め込み SQL では、ホスト変数 :CName および :CAddr を指定する INTO 節を使用して、選択された顧客の名前と州名をそれぞれローカル変数 CNameCAddr に返しています。

以下の例では、添え字付きのローカル変数を使用して同じ操作を実行します。

   &sql(SELECT Name,Home_State
        INTO :CInfo(1),:CInfo(2)
        FROM Sample.Person)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
      WRITE !,"Name is: ",CInfo(1)
      WRITE !,"State is: ",CInfo(2)

これらのホスト変数は、ユーザが指定した添え字を持つ単純なローカル変数です (:CInfo(1))。ただし、添え字を省略すると (:CInfo())、以下に示すように、InterSystems IRIS は SqlColumnNumber を使用して、ホスト変数の添え字付き配列に値を移入します。

以下の ObjectScript の例では、埋め込み SQL 文は、(WHERE 節の) 入力ホスト変数と (INTO 節の) 出力ホスト変数の両方を使用します。

  SET minval = 10000
  SET maxval = 50000
  &sql(SELECT Name,Salary INTO :outname, :outsalary
       FROM MyApp.Employee
       WHERE Salary > :minval AND Salary < :maxval)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
      WRITE !,"Name is: ",outname
      WRITE !,"Salary is: ",outsalary

以下の例では、入力ホスト変数に “簡略な正規化“ を行います。InterSystems IRIS では、入力変数の値は文字列として扱われ、正規化は行われませんが、埋め込み SQL では、この数字が 65 に正規化されて WHERE 節で等値比較が実行されます。

  SET x="+065.000"
  &sql(SELECT Name,Age
       INTO :a,:b
       FROM Sample.Person
       WHERE Age=:x)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
  WRITE !,"Input value is: ",x
  WRITE !,"Name value is: ",a
  WRITE !,"Age value is: ",b

以下の ObjectScript の例では、埋め込み SQL 文は、ホスト変数としてオブジェクト・プロパティを使用します。

   &sql(SELECT Name, Title INTO :obj.Name, :obj.Title
        FROM MyApp.Employee
        WHERE %ID = :id )

この場合、obj は、変更可能なプロパティ Name および Title を持つオブジェクトへの、有効な参照である必要があります。クエリに INTO 文が含まれているときにデータが返されない場合 (つまり SQLCODE が 100 の場合)、クエリの実行によりホスト変数の値が変更されている可能性があります。

列番号を添え字とするホスト変数

FROM 節に含まれるテーブルが 1 つの場合は、そのテーブルから選択されるフィールドのために添え字付きホスト変数を指定できます。例えば、論理配列 :myvar() などです。このローカル配列の値は、各フィールドの SqlColumnNumber を数値の添え字として使用して生成されます。この SqlColumnNumber は、select-list の順番ではなく、テーブル定義の列番号を表しています。(ビューのフィールドのために添え字付きホスト変数を使用することはできません)。

ホスト変数配列は、最下位レベルの添え字が省略されているローカル配列である必要があります。したがって、:myvar():myvar(5,)、および :myvar(5,2,) はすべて、有効なホスト変数の添え字付き配列です。

  • ホスト変数の添え字付き配列は、INSERTUPDATE、または INSERT OR UPDATE 文の VALUES 節で入力のために使用できます。ホスト変数配列が INSERT 文または UPDATE 文で使用された場合は、コンパイル時ではなく実行時に更新される列を定義できます。INSERT および UPDATE の使用法については、"InterSystems SQL リファレンス" でそれらのコマンドを参照してください。

  • ホスト変数の添え字付き配列は、SELECT または DECLARE 文の INTO 節で出力のために使用できます。SELECT での添え字付き配列の使用法は、以下の例で説明します。

以下の例では、SELECT は、Cdata 配列に指定のフィールドの値を追加します。Cdata() の要素は、SELECT 要素ではなく、テーブル列定義に対応します。したがって、Name フィールド、Age フィールド、および DOB フィールドはそれぞれ、Sample.Person の列 6、列 2、および列 3 です。

   &sql(SELECT Name,Age,DOB
        INTO :Cdata()
        FROM Sample.Person)
          IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
          ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
      WRITE !,"Name is: ",Cdata(6)
      WRITE !,"Age is: ",Cdata(2)
      WRITE !,"DOB is: ",$ZDATE(Cdata(3),1)

以下の例では、添え字付き配列のホスト変数を使用して、行のフィールド値をすべて返します。

   &sql(SELECT * INTO :Allfields()
        FROM Sample.Person)
          IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
          ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
      SET x=1
      WHILE x '="" {
      WRITE !,x," field is ",Allfields(x)
      SET x=$ORDER(Allfields(x))
      }

この WHILE ループは、単純な x=x+1 ではなく、$ORDER を使用してインクリメントされることに注意してください。これは、Sample.Person などの多くのテーブルで、非表示の列が存在する可能性があるためです。このような場合、列番号が不連続になります。

SELECT リストにテーブルのフィールドではない項目 (式や矢印構文のフィールドなど) が含まれている場合には、INTO 節に、コンマ区切りの配列ではないホスト変数も含める必要があります。以下の例では、定義されたテーブル列に対応する値を返す添え字付き配列のホスト変数と、定義されたテーブル列に対応しない値を返すホスト変数を組み合わせて使用しています。

   &sql(SELECT Name,Home_City,{fn NOW},Age,($HOROLOG-DOB)/365.25,Home_State
        INTO :Allfields(),:timestmp('now'),:exactage
        FROM Sample.Person)
          IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
          ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
      SET x=$ORDER(Allfields(""))
      WHILE x '="" {
      WRITE !,x," field is ",Allfields(x)
      SET x=$ORDER(Allfields(x)) }
      WRITE !,"date & time now is ",timestmp("now")
      WRITE !,"exact age is ",exactage

配列でないホスト変数は、列でない SELECT 項目と、数および順番が一致している必要があります。

添え字付き配列として使用するホスト変数には、以下の制限が適用されます。

  • 添え字付きリストは、選択するすべてのフィールドが、FROM 節の同じ 1 つのテーブルに存在する場合にのみ使用できます。これは、複数のテーブルからフィールドを選択すると、SqlColumnNumber の値が重複する可能性があるためです。

  • 添え字付きリストは、テーブルからフィールドを選択する場合にのみ使用できます。式や集計フィールドを対象として使用することはできません。これは、これらの select-list 項目には SqlColumnNumber の値がないからです。

ホスト変数配列の使用法の詳細は、"InterSystems SQL リファレンス" の "INTO 節" を参照してください。

NULL および未定義ホスト変数

定義されていない入力ホスト変数を指定した場合、埋め込み SQL はその値を NULL として処理します。

   NEW x
   &sql(SELECT Home_State,:x
        INTO :a,:b
        FROM Sample.Person)
          IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
          ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
     WRITE !,"The length of Home_State is: ",$LENGTH(a)
     WRITE !,"The length of x is: ",$LENGTH(b)

SQL の NULL は、ObjectScript の "" 文字列 (長さゼロの文字列) に相当します。

埋め込み SQL をコンパイルすると、すべての INTO 節の出力ホスト変数が ObjectScript "" 文字列 (長さゼロの文字列) として定義されます。ホスト変数に NULL を出力する場合、埋め込み SQL では、その値は ObjectScript の "" 文字列 (長さゼロの文字列) として処理されます。例えば、Sample.Person 内のいくつかのレコードに NULL の Spouse フィールドがあるとします。以下のクエリを実行します。

 &sql(SELECT Name,Spouse
    INTO :name, :spouse
    FROM Sample.Person
    WHERE Spouse IS NULL)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
    WRITE !,"Name: ",name," of length ",$LENGTH(name)," defined: ",$DATA(name)
    WRITE !,"Spouse: ",spouse," of length ",$LENGTH(spouse)," defined: ",$DATA(spouse)

ホスト変数 spouse は、NULL 値を表す "" (長さゼロの文字列) に設定されます。このため、ObjectScript $DATA 関数を使用して SQL フィールドが NULL かどうかを判断することはできません。NULL 値の SQL フィールドの出力ホスト変数を渡すと、$DATA は true を返します (変数が定義されます)。

テーブルのフィールドに長さゼロの SQL 文字列 ('') が含まれる場合 (アプリケーションが明示的にフィールドを SQL 文字列 '' に設定する場合など)、ホスト変数に、特別なマーカ値 $CHAR(0) (ASCII の 0 の文字を 1 つのみ含む、長さ 1 の文字列) が含まれます。これが、ObjectScript での長さゼロの SQL 文字列の表現です。長さゼロの SQL 文字列は使用しないことを強くお勧めします。

以下の例では、SQL の NULL と長さゼロの SQL 文字列からのホスト変数の出力を比較します。

 &sql(SELECT '',Spouse
    INTO :zls, :spouse
    FROM Sample.Person
    WHERE Spouse IS NULL)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
    WRITE "In ObjectScript"
    WRITE !,"ZLS is of length ",$LENGTH(zls)," defined: ",$DATA(zls)
       /* Length=1, Defined=1 */
    WRITE !,"NULL is of length ",$LENGTH(spouse)," defined: ",$DATA(spouse)
       /* Length=0, Defined=1 */

このホスト変数の NULL の動作は、サーバ・ベースのクエリ (埋め込み SQL とダイナミック SQL) に固有のものであることに注意してください。ODBC および JDBC では、NULL 値は ODBC または JDBC のインタフェースを使用して明示的に指定されます。

ホスト変数の有効性

  • 入力ホスト変数は、埋め込み SQL で変更されることはありません。

  • 出力ホスト変数は、SQLCODE = 0 のときに埋め込み SQL の後でのみ有効性が保証されます。

例えば、OutVal の以下の使用は、有効性が保証されません

InvalidExample
   SET InVal = "1234"
   SET OutVal = "None"
   &sql(SELECT Name
        INTO :OutVal
        FROM Sample.Person
        WHERE %ID=:InVal)
   IF OutVal="None" {           ; Improper Use 
   WRITE !,"No data returned"
   WRITE !,"SQLCODE=",SQLCODE }
   ELSE {
   WRITE !,"Name is: ",OutVal }

埋め込み SQL の実行前に設定された OutVal の値は、埋め込み SQL から返された後に IF コマンドで参照できません

代わりに、この例は SQLCODE 変数を使用して、以下のようなコードにします。

ValidExample
   SET InVal = "1234"
   &sql(SELECT Name
        INTO :OutVal
        FROM Sample.Person
        WHERE %ID=:InVal)
   IF SQLCODE'=0 { SET OutVal="None" 
      IF OutVal="None" {
      WRITE !,"No data returned"
      WRITE !,"SQLCODE=",SQLCODE } }
   ELSE {
   WRITE !,"Name is: ",OutVal }

埋め込み SQL では、出力行が正常に取得されたことを示す場合に SQLCODE 変数に 0 が設定されます。SQLCODE 値の 100 は、SELECT 条件に一致する行が見つからないことを示します。SQLCODE の負の数値は、SQL エラーの状態を示します。

ホスト変数とプロシージャ・ブロック

埋め込み SQL をプロシージャ・ブロックの中に記述する場合は、入力および出力のすべてのホスト変数をパブリックにする必要があります。そのためには、プロシージャ・ブロック先頭の PUBLIC セクションでその変数を宣言するか、その変数の名前の先頭に % 文字を使用します (これで自動的にパブリックになります)。ただし、ユーザ定義の % ホスト変数は自動的にパブリックになりますが、自動的に NEW は実行されないことに注意してください。このような変数に対する NEW は、必要に応じてユーザの責任で実行してください。%ROWCOUNT、%ROWID、%msg など一部の SQL % 変数は、"埋め込み SQL の変数" に説明されているように、自動的にパブリックになり、かつ自動的に NEW が実行されます。SQLCODE をパブリックとして宣言する必要があります。SQLCODE 変数の詳細は、"埋め込み SQL の変数" を参照してください。

以下のプロシージャ・ブロックの例では、ホスト変数 zipcity、および state と、SQLCODE 変数を PUBLIC として宣言しています。SQL システム変数 %ROWCOUNT、%ROWID、および %msg は、名前の先頭に % 文字が使用されているので既にパブリックになっています。その後、このプロシージャ・コードでは、SQLCODE、その他の SQL システム変数、および state ローカル変数に対して NEW コマンドを実行しています。

UpdateTest(zip,city)
  [SQLCODE,zip,city,state] PUBLIC {
  NEW SQLCODE,%ROWCOUNT,%ROWID,%msg,state
  SET state="MA"
  &sql(UPDATE Sample.Person
       SET Home_City = :city, Home_State = :state
       WHERE Home_Zip = :zip)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
        QUIT %ROWCOUNT
  }

SQL カーソル

カーソルはデータを指しているポインタであり、埋め込み SQL プログラムはカーソルを使用して、ポインタが指しているレコードに対する操作を実行できます。カーソルを使用すると、埋め込み SQL は結果セットを反復処理できます。埋め込み SQL はカーソルを使用して、複数のレコードからデータを返すクエリを実行できます。埋め込み SQL はカーソルを使用して、複数のレコードを更新または削除することもできます。

まず DECLARE 文を使用して SQL カーソルを宣言して、そのカーソルに名前を付ける必要があります。この DECLARE 文では、そのカーソルが指すレコードを指定する SELECT 文を記述します。次に、このカーソル名を OPEN cursor 文で指定します。次に、FETCH cursor 文を繰り返し発行して、SELECT 結果セットを反復処理します。次に、CLOSE cursor 文を発行します。

  • カーソル・ベースのクエリでは、DECLARE cursorname CURSOR FOR SELECT 文を使用してレコードが選択されて、(必要に応じて) 選択列の値が出力ホスト変数内に返されます。FETCH 文は結果セットを反復処理して、これらの変数を使用して選択された列の値を返します。

  • カーソル・ベースの DELETE 文や UPDATE 文では、DECLARE cursorname CURSOR FOR SELECT 文を使用して操作対象のレコードが選択されます。出力ホスト変数は指定されません。FETCH 文は、結果セットを反復処理します。DELETE 文や UPDATE 文に含まれている WHERE CURRENT OF 節によって、選択されたレコードに対して操作を実行するために現在のカーソル位置が特定されます。カーソル・ベースの DELETE および UPDATE の詳細は、"InterSystems SQL リファレンス" の "WHERE CURRENT OF" のページを参照してください。

カーソルは、複数のメソッドにまたがることができません。このため、同一クラス・メソッド内で 1 つのカーソルを宣言し、開き、フェッチして、終了する必要があります。.CSP ファイルから生成されたクラスなど、クラスとメソッドを生成するすべてのコードでこれを考慮することが重要です。

以下の例では、カーソルを使用してクエリを実行し、主デバイスへ結果を表示します。

 &sql(DECLARE C1 CURSOR FOR
    SELECT %ID,Name
    INTO :id, :name
    FROM Sample.Person
    WHERE Name %STARTSWITH 'A'
    ORDER BY Name
 )

 &sql(OPEN C1)
      QUIT:(SQLCODE'=0)
 &sql(FETCH C1)

 While (SQLCODE = 0) {
     Write id, ":  ", name,!        
    &sql(FETCH C1)
 }
    
 &sql(CLOSE C1)

この例は、以下を実行します。

  1. これは、カーソル C1 を宣言し、Name の順に並べられた一連の Person 行を返します。

  2. カーソルをオープンします。

  3. データの最後に達するまで、カーソルの FETCH を呼び出します。FETCH 呼び出しの後、さらにフェッチするデータがある場合は SQLCODE 変数は 0 に設定されます。FETCH への各呼び出しの後、返り値は DECLARE 文の INTO 節により指定されたホスト変数にコピーされます。

  4. カーソルをクローズします。

DECLARE カーソル文

DECLARE 文は、カーソル名と、カーソルを定義する SQL SELECT 文の両方を指定します。また、DECLARE 文は、そのカーソルを使用する文よりのルーチンにある必要があります。

カーソル名は、大文字と小文字を区別します。

カーソル名は、クラスまたはルーチンの中で一意である必要があります。そのため、再帰的に呼び出されるルーチンには、カーソル宣言を含めることができません。このような状況では、ダイナミック SQL を使用するほうが望ましいことがあります。

以下の例では、MyCursor という名前のカーソルを宣言します。

 &sql(DECLARE MyCursor CURSOR FOR
    SELECT Name, DOB
    FROM Sample.Person
    WHERE Home_State = :state
    ORDER BY Name
    )

DECLARE 文には、オプションの INTO 節が含まれていることがあります。この INTO 節では、カーソルが走査されたときにデータを受け取るローカル・ホスト変数の名前を指定します。例えば、上記の例に INTO 節を追加すると、以下のようになります。

 &sql(DECLARE MyCursor CURSOR FOR
    SELECT Name, DOB
    INTO :name, :dob
    FROM Sample.Person
    WHERE Home_State = :state
    ORDER BY Name
    )

INTO 節には、ホスト変数のコンマ区切りリスト、単一のホスト変数配列、またはそれら両方を組み合わせて含めることができます。コンマ区切りリストとして指定する場合、INTO 節のホスト変数の数は、カーソルの SELECT リスト内の列数と完全に一致する必要があります。一致していない場合は、文のコンパイル時に “カーディナリティ・ミスマッチ” エラーを受け取ることになります。

DECLARE 文に INTO 節が含まれない場合、INTO 節は FETCH 文の中に表す必要があります。INTO 節を FETCH 文ではなく DECLARE 文で指定すると、パフォーマンスが多少向上する可能性があります。

DECLARE は宣言であり実行文ではないため、SQLCODE 変数を設定したり削除したりすることはできません。

指定されたカーソルが既に宣言されている場合、コンパイルは失敗し、SQLCODE -52 エラー (カーソルは既に宣言されています) が表示されます。

DECLARE 文を実行しても、SELECT 文はコンパイルされません。SELECT 文は、OPEN 文の初回実行時にコンパイルされます。埋め込み SQL はルーチンのコンパイル時ではなく、SQL 実行時 (ランタイム) にコンパイルされます。

OPEN カーソル文

OPEN 文は、カーソルより後の部分を実行するために、カーソルを作成します。

 &sql(OPEN MyCursor)

OPEN 文を実行すると、DECLARE 文で見つかった埋め込み SQL コードがコンパイルされ、最適化されたクエリ・プランが作成され、クエリ・キャッシュが生成されます。OPEN を実行すると (SQL 実行時に)、リソースが見つからないエラー (未定義のテーブルやフィールドなど) が発行されます。

OPEN 呼び出しに成功すると、SQLCODE 変数が 0 に設定されます。

最初に OPEN 呼び出しを実行せずに、カーソルからデータを FETCH することはできません。

FETCH カーソル文

FETCH 文は、(カーソル・クエリで定義されているように) カーソルの次の行のデータをフェッチします。

 &sql(FETCH MyCursor)

FETCH 呼び出しの前にカーソルの DECLARE と OPEN を実行する必要があります。

FETCH 文には、INTO 節が含まれていることがあります。この INTO 節では、カーソルが走査されたときにデータを受け取るローカル・ホスト変数の名前を指定します。例えば、上記の例に INTO 節を追加すると、以下のようになります。

 &sql(FETCH MyCursor INTO :a, :b)

INTO 節には、ホスト変数のコンマ区切りリスト、単一のホスト変数配列、またはそれら両方を組み合わせて含めることができます。コンマ区切りリストとして指定する場合、INTO 節のホスト変数の数は、カーソルの SELECT リスト内の列数と完全に一致する必要があります。一致していない場合は、文のコンパイル時に SQLCODE -76 “カーディナリティ・ミスマッチ”・エラーを受け取ることになります。

通常、INTO 節は FETCH 文ではなく DECLARE 文で指定されます。DECLARE 文と FETCH 文両方の SELECT クエリに INTO 節が含まれる場合、DECLARE 文により指定されたホスト変数のみが設定されます。FETCH 文にのみ INTO 節が含まれる場合、FETCH 文により指定されたホスト変数が設定されます。

FETCH がデータを取得する場合、SQLCODE 変数は 0 に設定されます。フェッチするデータがない場合 (または、これ以上データがない場合)、SQLCODE は 100 に設定されます (これ以上データがないことを意味します)。 ホスト変数値は、SQLCODE=0 の場合にのみ使用してください。

クエリによっては、最初の FETCH 呼び出しが別のタスク (一時的なデータ構造内の値の並べ替えなど) を実行する場合もあります。

CLOSE カーソル文

CLOSE 文は、カーソルの実行を終了します。

 &sql(CLOSE MyCursor)

CLOSE 文は、クエリの実行に使用したテンポラリ・ストレージをクリーンアップします。CLOSE 呼び出しに失敗したプログラムでは、リソース・リークが起こる可能性があります (テンポラリ・データベースの IRISTEMP の不必要な増加など)。

CLOSE の呼び出しに成功すると、SQLCODE 変数が 0 に設定されます。そのため、カーソルを閉じる前に、最後の FETCH が SQLCODE を 0 を設定するかまたは 100 に設定するかを調べる必要があります。

埋め込み SQL の変数

以下の変数には、埋め込み SQL で特殊な使用方法があります。これらのローカル変数名では、大文字と小文字が区別されます。プロセス開始時には、これらの変数は未定義です。これらの変数は埋め込み SQL の操作によって設定されます。これらの変数は、SET コマンドを使用して直接設定することも、NEW コマンドを使用して未定義状態にリセットすることもできます。すべてのローカル変数と同様に、値は、プロセスが継続している間、または NEW を使用して未定義状態に設定されるか別の値に設定されるまで保持されます。例えば、一部の埋め込み SQL 操作については、それらの操作が正常に実行されても %ROWID は設定されません。これらの操作の実行後は、%ROWID は定義されないか、前の値に設定されたままになります。

これらのローカル変数はダイナミック SQL によって設定されません。(SQL シェルと管理ポータルの SQL インタフェースによってダイナミック SQL が実行されることに注意してください。)代わりに、ダイナミック SQL では対応するオブジェクト・プロパティが設定されます。

次の ObjectScript 特殊変数は、埋め込み SQL で使用されます。これらの特殊変数名では、大文字と小文字が区別されません。プロセス開始時には、これらの変数は何らかの値に初期化されます。これらの変数は埋め込み SQL の操作によって設定されます。これらの変数は、SET コマンドや NEW コマンドを使用して直接設定することはできません。

InterSystems IRIS では、埋め込み SQL の処理中に、定義済みの InterSystems IRIS 埋め込み SQL インタフェースの中でこれらのどの変数でも設定できます。

クラス・メソッド (ProcedureBlock=ON) に埋め込み SQL を記述した場合、これらのすべての変数が自動的に PublicList に配置され、SQL 文で使用する SQLCODE、%ROWID、%ROWCOUNT、%msg、およびすべての非 % 変数に NEW 操作が実行されます。メソッドからの参照またはメソッドへの参照により、それらの変数を渡すことができます。参照により渡される変数は、クラス・メソッド・プロシージャ・ブロック内での自動的な NEW 操作が行われません。

ルーチンに埋め込み SQL を記述した場合、プログラミングの段階で、埋め込み SQL を呼び出す前に %msg、%ROWCOUNT、%ROWID、および SQLCODE の各変数を NEW コマンドで新規作成しておく必要があります。NEW を使用してこれらの変数を新規作成すると、これらの変数の以前の設定に対する干渉が防止されます。<FRAMESTACK> エラーを防ぐために、繰り返しサイクル内でこの NEW 操作を実行しないでください。

%msg

システム定義のエラー・メッセージ文字列を含む変数。InterSystems SQL は、SQLCODE を負の整数 (エラーを示す) に設定した場合にのみ、%msg を設定します。SQLCODE が 0 または 100 に設定されている場合は、%msg 変数は以前の値のまま変更されません。

この動作は、ダイナミック SQL の対応する %MessageOpens in a new tab プロパティとは異なります。このプロパティは現在エラーがない場合に空の文字列に設定されます。

場合により、特定の SQLCODE エラー・コードを、SQLCODE を生成したさまざまな条件を記述して、複数の %msg 文字列に関連付けることができます。%msg はユーザ定義のメッセージ文字列を取ることもできます。これは、一般的には、トリガ・コードにより %ok=0 が明示的に設定されたときに、トリガからユーザ定義メッセージを発行して、トリガを中止するために使用します。

SQL コードの実行時に、エラー・メッセージ文字列は、そのプロセスに使用される NLS 言語で生成されます。SQL コードは異なる NLS 言語環境でコンパイルされる可能性があり、メッセージは実行時の NLS 環境に従って生成されます。"$SYS.NLS.Locale.LanguageOpens in a new tab" を参照してください。

%ROWCOUNT

特定の文によって影響される行の数を示す整数カウンタ。

  • INSERTUPDATEINSERT OR UPDATE、および DELETE は %ROWCOUNT を影響される行の数に設定します。明示的な値が指定された INSERT コマンドによって影響を与えることができるのは 1 行のみであるため、このコマンドによって %ROWCOUNT は 0 または 1 に設定されます。INSERT クエリ結果、UPDATE、または DELETE は複数の行に影響を与えることができるため、%ROWCOUNT は 0 または正の整数に設定される可能性があります。

  • TRUNCATE TABLE は、削除された行数や行が削除されたかどうかに関係なく、常に %ROWCOUNT を –1 に設定します。このため、削除された実際の行数を特定するには、TRUNCATE TABLE の前にテーブルに対して COUNT(*) を実行するか、TRUNCATE TABLE ではなく DELETE を使用してテーブル内のすべての行を削除します。

  • カーソルが宣言されていない SELECT は単一の行しか処理できないため、単純な SELECT の実行は常に %ROWCOUNT を 1 (取得された選択条件に一致する行が 1 行) または 0 (選択条件に一致する行なし) のどちらかに設定します。

  • DECLARE cursorname CURSOR FOR SELECT によって %ROWCOUNT は初期化されません。%ROWCOUNT は SELECT の実行後に変更されず、OPEN cursorname の実行後も変更されないままです。FETCH が初めて正常に実行されると、%ROWCOUNT が設定されます。クエリ選択条件に一致する行がない場合、FETCH は %ROWCOUNT=0 に設定します。FETCH がクエリ選択条件に一致する行を取得した場合、%ROWCOUNT=1 に設定されます。行を取得する後続の各 FETCH は、%ROWCOUNT をインクリメントします。CLOSE 時、または FETCH が SQLCODE 100 (データがない、またはこれ以上データがない) を発行すると、%ROWCOUNT には検出された行の総数が含まれます。

この SELECT の動作は、ダイナミック SQL の対応する %ROWCOUNTOpens in a new tab プロパティとは異なります。このプロパティはクエリ実行の完了時に 0 に設定され、プログラムがクエリによって返された結果セットの繰り返し処理を行ったときにのみインクリメントされます。

SELECT クエリが集約関数のみを返す場合、すべての FETCH で %ROWCOUNT=1 が設定されます。最初の FETCH は、テーブルにデータがない場合でも、常に %SQLCODE=0 で完了します。後続の FETCH は %SQLCODE=100 で完了し、%ROWCOUNT=1 を設定します。

以下の埋め込み SQL の例は、カーソルを宣言し、FETCH を使用してテーブル内の各行を取り出します。データの最後に達すると (SQLCODE=100)、%ROWCOUNT には、取得された行数が含まれます。

   SET name="LastName,FirstName",state="##"
   &sql(DECLARE EmpCursor CURSOR FOR 
        SELECT Name, Home_State
        INTO :name,:state FROM Sample.Person
        WHERE Home_State %STARTSWITH 'M')
   WRITE !,"BEFORE: Name=",name," State=",state
   &sql(OPEN EmpCursor)
      QUIT:(SQLCODE'=0)
   FOR { &sql(FETCH EmpCursor)
        QUIT:SQLCODE  
        WRITE !,"Row fetch count: ",%ROWCOUNT
        WRITE " Name=",name," State=",state
 }
   WRITE !,"Final Fetch SQLCODE: ",SQLCODE
   &sql(CLOSE EmpCursor)
   WRITE !,"AFTER: Name=",name," State=",state
   WRITE !,"Total rows fetched: ",%ROWCOUNT

以下の埋め込み SQL の例では、UPDATE が実行され、変更によって影響される行の数が設定されます。

 &sql(UPDATE MyApp.Employee 
     SET Salary = (Salary * 1.1)
     WHERE Salary < 50000)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
  WRITE "Employees: ", %ROWCOUNT,!

所定のプロセス内の埋め込み SQL 文はすべて、%ROWCOUNT 変数を変更することに注意してください。%ROWCOUNT によって指定される値が必要な場合は、必ずその値を取得してからその他の埋め込み SQL 文を実行してください。埋め込み SQL を呼び出す方法によっては、埋め込み SQL の実行に入る前に NEW コマンドで変数 %ROWCOUNT を新規作成しておく必要があります。

%ROWCOUNT の値は、トランザクションの明示的なロール・バックによる影響を受けません。例えば、以下はロール・バックされているにもかかわらず、変更があったことをレポートします。

 TSTART // start an explicit transaction
  NEW SQLCODE,%ROWCOUNT,%ROWID
 &sql(UPDATE MyApp.Employee 
     SET Salary = (Salary * 1.1)
     WHERE Salary < 50000)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}

 TROLLBACK // force a rollback; this will NOT modify %ROWCOUNT
 Write "Employees: ", %ROWCOUNT,!

暗黙のトランザクション (UPDATE が制約のチェックに失敗した場合など) は、%ROWCOUNT により反映されます。

%ROWID

プロセスを初期化したときに、%ROWID は未定義です。NEW %ROWID コマンドを発行すると、%ROWID は未定義状態にリセットされます。%ROWID は、以下で説明している埋め込み SQL 操作によって設定されます。その操作が正常に実行されなかった場合や、正常に実行されたがどの行も取得または変更されなかった場合は、%ROWID の値は以前の値のまま変更されません。すなわち、未定義のままか、以前の埋め込み SQL 操作によって設定された値のままとなります。このため、それぞれの埋め込み SQL 操作の前に NEW %ROWID を実行することが重要です。

%ROWID は、以下の操作の影響を受ける最後の行の RowID に設定されます。

  • INSERTUPDATEINSERT OR UPDATE、または DELETE:単一行を対象にした操作の後は、%ROWID 変数には、挿入、更新、または削除されたレコードにシステムによって割り当てられた RowID (オブジェクト ID) の値が含まれています。複数行を対象にした操作の後は、%ROWID 変数には、最後に挿入、更新、または削除されたレコードにシステムによって割り当てられた RowID (オブジェクト ID) の値が含まれています。どのレコードも挿入、更新、または削除されていない場合は、%ROWID 変数の値は変更されません。TRUNCATE TABLE は %ROWID を設定しません。

  • カーソル・ベースの SELECTDECLARE cursorname CURSOR 文と OPEN cursorname 文では %ROWID は初期化されないため、%ROWID の値は以前の値から変更されません。FETCH が初めて正常に実行されると、%ROWID が設定されます。行を取得する後続の各 FETCH は、%ROWID を現在の RowID 値にリセットします。FETCH は、更新可能なカーソルの行を取得すると、%ROWID を設定します。更新可能なカーソルとは、最上位の FROM 節にテーブル名か更新可能なビュー名のいずれかの要素が 1 つだけ含まれるカーソルのことです。カーソルが更新可能でない場合、%ROWID は変更されません。クエリ選択条件と一致する行がない場合、FETCH は以前の %ROWID 値 (ある場合) を変更しません。CLOSE 時、または FETCH が SQLCODE 100 (データがない、またはこれ以上データがない) を発行すると、%ROWID には取得された最後の行の RowID が含まれます。

    カーソル・ベースの SELECTDISTINCT キーワードまたは GROUP BY 節を使用すると、%ROWID は設定されません。%ROWID 値に以前の値がある場合、%ROWID 値はその値から変更されません。

    集約関数を含むカーソル・ベースの SELECT は、集約関数値のみを返す場合、%ROWID を設定しません。フィールド値と集約関数値の両方を返す場合、すべての FETCH の %ROWID 値は、クエリによって返された最後の行の RowID に設定されます。

  • カーソルが宣言されていない SELECT は、%ROWID を設定しません。%ROWID は単純な SELECT 文の完了時に未変更のままとなります。

ダイナミック SQL では、対応する %ROWIDOpens in a new tab プロパティは最後に挿入、更新、または削除されたレコードの RowID 値を返します。ダイナミック SQL では、SELECT クエリの実行時に %ROWID プロパティの値は返されません。

以下のメソッド呼び出しを使用することによって、ObjectScript から現在の %ROWID を取得できます。

  WRITE $SYSTEM.SQL.GetROWID()

INSERTUPDATEDELETETRUNCATE TABLE、またはカーソル・ベースの SELECT 操作の後に、LAST_IDENTITY という SQL 関数は、直前に変更されたレコードの IDENTITY フィールドの値を返します。テーブルに IDENTITY フィールドがない場合、この関数は、直前に変更されたレコードの RowID を返します。

SQLCODE

埋め込み SQL クエリを実行した後、出力ホスト変数を処理する前に SQLCODE をチェックする必要があります。

SQLCODE=0 の場合、クエリは正常に完了し、データを返しています。出力ホスト変数にはフィールド値が含まれています。

SQLCODE=100 の場合、クエリは正常に完了していますが、出力ホスト変数値が異なることがあります。以下のいずれかです。

  • クエリは 1 つ以上のデータ行を返した後 (SQLCODE=0)、データの最後に達しました (SQLCODE=100)。この場合、出力ホスト変数は、返された最後の行のフィールド値に設定されます。%ROWCOUNT>0 です。

  • クエリはデータを返しませんでした。この場合、出力ホスト変数は NULL 文字列に設定されます。%ROWCOUNT=0 です。

クエリが集約関数のみを返す場合、テーブルにデータがない場合でも、最初の FETCH は常に SQLCODE=0 および %ROWCOUNT=1 で完了します。2 番目の FETCH は、SQLCODE=100 および %ROWCOUNT=1 で完了します。テーブルにデータがない場合や、クエリ条件と一致するデータがない場合、クエリは出力ホスト変数を適宜 0 または空の文字列に設定します。

SQLCODE が負数の場合、クエリは失敗し、エラー状態になっています。これらのエラー・コードのリストおよび詳細は、"InterSystems IRIS エラー・リファレンス" の "SQLCODE 値とエラー・メッセージ" の章を参照してください。

埋め込み SQL を呼び出す方法によっては、埋め込み SQL の実行に入る前に NEW コマンドで変数 SQLCODE を新規作成しておく必要があります。トリガ・コード内で、SQLCODE をゼロ以外の値に設定すると、自動的に %ok=0 が設定され、トリガ処理が中止されてロール・バックされます。

ダイナミック SQL では、対応する %SQLCODEOpens in a new tab プロパティは SQL エラー・コードの値を返します。

$TLEVEL

トランザクション・レベルのカウンタ。InterSystems SQL は $TLEVEL を 0 に初期化します。現在のトランザクションがない場合、$TLEVEL は 0 です。

  • 最初の START TRANSACTION は、$TLEVEL を 1 に設定します。追加の START TRANSACTION 文は、$TLEVEL に影響を与えません。

  • SAVEPOINT 文 は $TLEVEL を 1 インクリメントします。

  • ROLLBACK TO SAVEPOINT pointname 文は、$TLEVEL をデクリメントします。デクリメントの量は、セーブポイントによって決定します。

  • COMMIT$TLEVEL を 0 にリセットします。

  • ROLLBACK$TLEVEL を 0 にリセットします。

また、%INTRANSACTION 文を使用すると、トランザクションが処理中かどうかを判定できます。

$TLEVEL は、ObjectScript トランザクション・コマンドによって設定することもできます。詳細は、"ObjectScript リファレンス" の "$TLEVEL" 特殊変数を参照してください。

$USERNAME

SQL ユーザ名は、InterSystems IRIS ユーザ名と同じであり、ObjectScript の $USERNAME 特殊変数に格納されています。ユーザ名は、システム全体の既定のスキーマとして、またはスキーマ検索パス内の要素として使用できます。

永続クラスのメソッドの埋め込み SQL

以下の例では、クラス・メソッドとインスタンス・メソッド (どちらにも埋め込み SQL が含まれます) を含む永続クラスを示します。

Class Sample.MyClass Extends %Persistent [DdlAllowed]
 { 
 ClassMethod NameInitial(Myval As %String) As %String [SqlProc]
  {
     &sql(SELECT Name INTO :n FROM Sample.Stuff WHERE Name %STARTSWITH :Myval)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE  RETURN %msg}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  RETURN}
   WRITE "Hello "  RETURN n
  }
 Method CountRows() As %Integer
  {
   &sql(SELECT COUNT(*) INTO :count FROM Sample.Stuff)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE  RETURN %msg}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  RETURN}
   WRITE "Number of rows is "  RETURN count
  }
 }

クラス・メソッドは、以下のように呼び出します。

  WRITE ##class(Sample.MyClass).NameInitial("G")

インスタンス・メソッドは、以下のように呼び出します。

  SET x=##class(Sample.MyClass).%New()
  WRITE x.CountRows()

これらのメソッドを正常にコンパイルするのに、テーブルやフィールドなどの SQL エンティティが存在する必要はありません。実行時に SQL エンティティの存在チェックが実行されるため、埋め込み SQL メソッドには SQLCODE テスト・ロジックが含まれている必要があります。

コードを実行することなく、埋め込み SQL で指定された SQL エンティティの存在をテストすることができます。これについては、"埋め込み SQL コードの検証" を参照してください。

埋め込み SQL コードの検証

次の 2 つの方法で、コードを実行せずに埋め込み SQL コードを検証できます。

  • /compileembedded=1 修飾子を使用して、埋め込み SQL コードを含むルーチンをコンパイルします。

  • $SYSTEM.OBJ.GenerateEmbedded()Opens in a new tab メソッドを使用して、複数の埋め込み SQL ルーチンをコンパイルします。

  • 管理ポータルの SQL インタフェースの [プラン表示] オプションを使用して、埋め込み SQL コードをテストします。

/compileembedded 修飾子でのコンパイル

$SYSTEM.OBJ クラスのコンパイル・クラス・メソッドを使用し、qspec 引数で /compileembedded=1 修飾子を指定して、埋め込み SQL コードを検証できます。/Compileembedded のデフォルトは 0 です。

ターミナルから SetQualifiers()Opens in a new tab メソッドを使用して、既定で /compileembedded=1 修飾子の使用を指定できます。

USER>DO $SYSTEM.OBJ.SetQualifiers("/compileembedded=1")    /* sets /compileembedded for current namespace */
USER>DO $SYSTEM.OBJ.SetQualifiers("/compileembedded=1",1)  /* sets /compileembedded for all namespaces */

/compileembedded を含む qspec 修飾子のリストを表示するには、以下を呼び出します。

USER>DO $SYSTEM.OBJ.ShowQualifiers()

既定以外の修飾子設定は、ShowQualifiers()Opens in a new tab 表示の最後に表示されます。

スタジオで、[ツール]→[オプション]→[コンパイラ]→[フラグと最適化]→[フラグ] フィールドに移動して、/compileembedded=1 修飾子を設定できます。これは、"スタジオ・オプションの設定" で説明されています。

[プラン表示] を使用したテスト

管理ポータルの SQL インタフェースを使用して、コードを実行することなく、埋め込み SQL コードを検証できます。この処理では、SQL 構文の検証と指定された SQL エンティティの存在チェックの両方が行われます。

管理ポータルの [システム・エクスプローラ] オプションで、[SQL] オプションを選択して [クエリ実行] コード領域を表示します。

  1. 埋め込み SQL クエリを入力します。例 : SELECT Name INTO :n FROM Sample.MyTest または DECLARE MyCursor CURSOR FOR SELECT Name,Age INTO :n,:a FROM Sample.MyTest WHERE Age > 21 FOR READ ONLY

  2. [プラン表示] ボタンを押して、コードを確認します。コードが有効な場合、[プラン表示] にクエリ・プランが表示されます。コードが無効な場合、[プラン表示] に SQLCODE エラー値とメッセージが表示されます。

    INTO 節がない場合、INTO 節は FETCH 文で指定される可能性があるため、[プラン表示] の検証でエラーは表示されません。INTO 節にエラーが含まれるか、INTO 節が間違った場所にある場合、[プラン表示] で該当するエラーが発行されます。

[実行] ボタンを使用して、埋め込み SQL コードを実行することはできません。

埋め込み SQL の監査

InterSystems IRIS では、埋め込み SQL 文の監査をオプションでサポートしています。埋め込み SQL の監査は、以下の 2 つの要件が満たされる場合に実行されます。

  1. %System/%SQL/EmbeddedStatement システム監査イベントがシステム全体で有効化されている場合。既定では、このシステム監査イベントは有効化されていません。有効にするには、管理ポータルに移動し、[システム管理][セキュリティ][監査][システムイベントを構成] の順に選択します。

  2. 埋め込み SQL 文を含むルーチンには、#sqlcompile audit マクロ・プリプロセッサ指示文が含まれている必要があります。この指示文が ON に設定されている場合は、コンパイルされたルーチン内でその指示文に続く埋め込み SQL 文が実行時に監査されます。

監査の情報は、監査データベースに記録されます。監査データベースを表示するには、管理ポータルに移動し、[システム管理][セキュリティ][監査][監査データベースの閲覧] の順に選択します。EmbeddedStatement に [イベント名] フィルタを設定して、[監査データベースの閲覧] を埋め込み SQL 文に制限することができます。監査データベースには、埋め込み SQL 文のタイプを指定する時間 (ローカル・タイムスタンプ)、ユーザ、PID (プロセス Id)、および説明がリストされます (SQL SELECT Statement など)。

イベントの [詳細] リンクを選択することで、[イベントデータ] などの追加情報をリストできます。イベント・データには、実行された SQL 文と、文の入力引数の値が含まれます。以下に例を示します。

SELECT TOP :n Name,ColorPreference INTO :name,:color FROM Sample.Stuff WHERE Name %STARTSWITH :letter 
Parameter values: 
n=5 
letter="F"

InterSystems IRIS では、ダイナミック SQL 文 (Event Name=DynamicStatement) および ODBC および JDBC 文 (Event Name=XDBCStatement) の監査もサポートしています。

FeedbackOpens in a new tab