埋め込み 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)
このクエリは、ホスト変数の name、dob、および 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 節を使用して、選択された顧客の名前と州名をそれぞれローカル変数 CName と CAddr に返しています。
以下の例では、添え字付きのローカル変数を使用して同じ操作を実行します。
&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,) はすべて、有効なホスト変数の添え字付き配列です。
-
ホスト変数の添え字付き配列は、INSERT、UPDATE、または 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 のインタフェースを使用して明示的に指定されます。
ホスト変数の有効性
例えば、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 の変数" を参照してください。
以下のプロシージャ・ブロックの例では、ホスト変数 zip、city、および 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 文を発行します。
カーソルは、複数のメソッドにまたがることができません。このため、同一クラス・メソッド内で 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)
この例は、以下を実行します。
-
これは、カーソル C1 を宣言し、Name の順に並べられた一連の Person 行を返します。
-
カーソルをオープンします。
-
データの最後に達するまで、カーソルの FETCH を呼び出します。FETCH 呼び出しの後、さらにフェッチするデータがある場合は SQLCODE 変数は 0 に設定されます。FETCH への各呼び出しの後、返り値は DECLARE 文の INTO 節により指定されたホスト変数にコピーされます。
-
カーソルをクローズします。
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
特定の文によって影響される行の数を示す整数カウンタ。
-
INSERT、UPDATE、INSERT 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 に設定されます。
-
INSERT、UPDATE、INSERT OR UPDATE、または DELETE:単一行を対象にした操作の後は、%ROWID 変数には、挿入、更新、または削除されたレコードにシステムによって割り当てられた RowID (オブジェクト ID) の値が含まれています。複数行を対象にした操作の後は、%ROWID 変数には、最後に挿入、更新、または削除されたレコードにシステムによって割り当てられた RowID (オブジェクト ID) の値が含まれています。どのレコードも挿入、更新、または削除されていない場合は、%ROWID 変数の値は変更されません。TRUNCATE TABLE は %ROWID を設定しません。
-
カーソル・ベースの SELECT:DECLARE cursorname CURSOR 文と OPEN cursorname 文では %ROWID は初期化されないため、%ROWID の値は以前の値から変更されません。FETCH が初めて正常に実行されると、%ROWID が設定されます。行を取得する後続の各 FETCH は、%ROWID を現在の RowID 値にリセットします。FETCH は、更新可能なカーソルの行を取得すると、%ROWID を設定します。更新可能なカーソルとは、最上位の FROM 節にテーブル名か更新可能なビュー名のいずれかの要素が 1 つだけ含まれるカーソルのことです。カーソルが更新可能でない場合、%ROWID は変更されません。クエリ選択条件と一致する行がない場合、FETCH は以前の %ROWID 値 (ある場合) を変更しません。CLOSE 時、または FETCH が SQLCODE 100 (データがない、またはこれ以上データがない) を発行すると、%ROWID には取得された最後の行の RowID が含まれます。
カーソル・ベースの SELECT で DISTINCT キーワードまたは 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()
INSERT、UPDATE、DELETE、TRUNCATE TABLE、またはカーソル・ベースの SELECT 操作の後に、LAST_IDENTITY という SQL 関数は、直前に変更されたレコードの IDENTITY フィールドの値を返します。テーブルに IDENTITY フィールドがない場合、この関数は、直前に変更されたレコードの RowID を返します。
SQLCODE
埋め込み SQL クエリを実行した後、出力ホスト変数を処理する前に SQLCODE をチェックする必要があります。
SQLCODE=0 の場合、クエリは正常に完了し、データを返しています。出力ホスト変数にはフィールド値が含まれています。
SQLCODE=100 の場合、クエリは正常に完了していますが、出力ホスト変数値が異なることがあります。以下のいずれかです。
クエリが集約関数のみを返す場合、テーブルにデータがない場合でも、最初の 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 です。
また、%INTRANSACTION 文を使用すると、トランザクションが処理中かどうかを判定できます。
$TLEVEL は、ObjectScript トランザクション・コマンドによって設定することもできます。詳細は、"ObjectScript リファレンス" の "$TLEVEL" 特殊変数を参照してください。