INTO (SQL)
構文
INTO :hostvar1 [,:hostvar2]...
概要
INTO 節とホスト変数は、埋め込み SQL内でのみ使用されます。ホスト変数は、ダイナミック SQL では使用されません。ダイナミック SQL では、同様の出力変数機能が %SQL.StatementOpens in a new tab クラスに用意されています。ODBC、JDBC、またはダイナミック SQL を介して処理される SELECT クエリで INTO 節を指定すると、SQLCODE -422 エラーが発生します。
INTO 節は、SELECT、DECLARE、または FETCH 文で使用できます。INTO 節は、これら 3 つのどの文でもまったく同じです。このページの例はすべて、SELECT 文を対象としています。DECLARE および FETCH での使用法は、"SQL カーソル" を参照してください。
INTO 節は、SELECT の select-item リスト内で取得 (または計算) された値を使用して、対応する出力ホスト変数を設定し、これらの返されたデータ値を ObjectScript で使用できるようにします。SELECT 内では、オプションの INTO 節は select-item リストと FROM 節の間に配置します。
埋め込み SQL のコンパイル時に、出力ホスト変数は空文字列に初期化されます。これにより、実行時の <UNDEFINED> エラーを防止します。したがって、ホスト変数に意味のある値が含まれるのは、SQLCODE=0 の場合のみです。出力ホスト変数の値を使用する前に、必ず SQLCODE を確認してください。また、SQLCODE=100 の場合や、SQLCODE が負の数値の場合は、これらの変数の値を使用しないでください。
ホスト変数
ホスト変数には単一の値のみを含めることができます。したがって、埋め込み SQL 内の SELECT では 1 行のデータのみが取得されます。既定では、この行はテーブルの最初の行になります。当然ながら、WHERE 条件を使用して対象行を制限することで、テーブルの他の行からデータを取得できます。
埋め込み SQL で、複数の行からデータを返すには、カーソルを宣言してから、連続する各行について FETCH を発行します。INTO 節のホスト変数は、DECLARE クエリ内または FETCH 内で指定できます。
INTO 節のホスト変数は、以下の 2 つのいずれかの方法 (または両方の組み合わせ) で指定できます。
含まれるプログラム内でのホスト変数の値の使用に関する重要な制限については、"ホスト変数" を参照してください。
ホスト言語が変数のデータ型を宣言する場合、すべてのホスト変数は SELECT 文を呼び出す前にホスト言語で宣言される必要があります。取得したフィールド値のデータ型は、ホスト変数の宣言と一致する必要があります (ObjectScript では変数にデータ型を宣言しません)。
ホスト変数リストの使用
INTO 節でホスト変数リストを指定する際は、以下の規則が適用されます。
-
INTO 節内のホスト変数の数は、select-item リスト内で指定されたフィールドの数と一致する必要があります。選択したフィールドの数とホスト変数の数が異なる場合、SQL は "cardinality mismatch" エラーを返します。
-
選択したフィールドとホスト変数は、相対的な位置によって一致させます。したがって、これらの 2 つのリスト内の対応する項目は同じシーケンスで表示される必要があります。
-
リストされたホスト変数は、添え字なし変数と添え字付き変数のどのような組み合わせでもかまいません。
-
リストされたホスト変数は、集約値 (カウント値、合計値、平均値など) または関数値を返すことができます。
-
リストされたホスト変数は、%CLASSNAME と %TABLENAME の値を返すことができます。
-
リストされたホスト変数は、複数のテーブルを扱う SELECT からフィールド値を返すことも、FROM 節がない SELECT から値を返すこともできます。
以下の例では、4 つのフィールドを選択して、4 つのホスト変数のリストに格納します。この例のホスト変数は添え字付きです。
&sql(SELECT %ID,Home_City,Name,SSN
INTO :mydata(1),:mydata(2),:mydata(3),:mydata(4)
FROM Sample.Person
WHERE Home_State='MA' )
IF SQLCODE=0 {
FOR i=1:1:15 {
IF $DATA(mydata(i)) {
WRITE "field ",i," = ",mydata(i),! }
} }
ELSE {WRITE "SQLCODE=",SQLCODE,! }
さらなる例については、下記の "ホスト変数リストの例" を参照してください。
ホスト変数配列の使用
ホスト変数配列では、単一の添え字付き変数に選択されたすべてのフィールド値を格納します。この配列には、select-item リスト内のフィールドの順序ではなく、テーブル内のフィールド定義の順序に従って値が格納されます。
INTO 節でホスト変数配列を使用する際は、以下の規則が適用されます。
-
select-item リストで指定されたフィールドは、選択されて、単一のホスト変数の添え字に格納されます。したがって、select-item リストの項目数をホスト変数の数と一致させる必要はありません。
-
ホスト変数の添え字には、テーブル定義内の対応するフィールド位置が割り当てられます。例えば、テーブル定義で定義された 6 番目のフィールドは mydata(6) に対応しています。指定された select-item に対応していない添え字はすべて、未定義のままになります。select-item 内の項目の順序は、添え字にどのように値が割り当てられるかに影響を与えません。
-
ホスト変数配列は、単一のテーブルからのフィールド値のみを返すことができます。
-
ホスト変数配列は、フィールド値のみを返すことができます。ホスト変数配列は、集約値 (カウント値、合計値、平均値など)、関数値、および %CLASSNAME や %TABLENAME の値を返すことはできません。(これらの値を返すには、ホスト変数リスト項目とホスト変数配列を組み合わせたホスト変数引数を指定します。)
以下の例では、4 つのフィールドを選択して、単一のホスト変数配列に格納します。
&sql(SELECT %ID,Home_City,Name,SSN
INTO :mydata()
FROM Sample.Person
WHERE Home_State='MA' )
IF SQLCODE=0 {
FOR i=0:1:15 {
IF $DATA(mydata(i)) {
WRITE "field ",i," = ",mydata(i),! }
} }
ELSE {WRITE "SQLCODE=",SQLCODE,! }
さらなる例については、下記の "ホスト変数配列の例" を参照してください。
詳細は、"添え字付き配列としてのホスト変数" を参照してください。
引数
:hostvar1
ホスト言語で宣言された出力ホスト変数です。INTO 節内で指定すると、変数名の前にコロン (:) が付きます。ホスト変数は、ローカル変数 (添え字なしでも添え字付きでも可) か、オブジェクト・プロパティのいずれかです。複数の変数は、コンマ区切りリスト、単一の添え字付き配列変数、またはコンマ区切りリストと単一の添え字付き配列変数の組み合わせとして指定できます。
フィールド値を返すホスト変数
以下の埋め込み SQL の例では、テーブルの最初のレコードから 3 つのフィールドを選択し (埋め込み SQL は常に単一のレコードを取得します)、INTO を使用して 3 つの対応する添え字なしホスト変数を設定します。これらの変数は ObjectScript WRITE コマンドによって使用されます。埋め込み SQL から戻ったらすぐに、プログラム内で SQLCODE 変数をテストすることをお勧めします。SQLCODE が 0 でない場合、出力ホスト変数の値は空文字列に初期化されます。
WRITE !,"Going to get the first record"
&sql(SELECT Home_State, Name, Age
INTO :state, :name, :age
FROM Sample.Person)
IF SQLCODE=0 {
WRITE !," Name=",name
WRITE !," Age=",age
WRITE !," Home State=",state }
ELSE {
WRITE !,"SQL error ",SQLCODE }
以下の埋め込み SQL の例では、2 つのテーブルの結合によって得られた 1 つの行からフィールド値を返します。複数のテーブルからフィールドを返す場合は、ホスト変数リストを使用する必要があります。
&sql(SELECT P.Name,E.Title,E.Name,P.%TABLENAME,E.%TABLENAME
INTO :name(1),:title,:name(2),:ptname,:etname
FROM Sample.Person AS P LEFT JOIN
Sample.Employee AS E ON E.Name %STARTSWITH 'B'
WHERE P.Name %STARTSWITH 'A')
IF SQLCODE=0 {
WRITE ptname," = ",name(1),!
WRITE etname," = ",title,!
WRITE etname," = ",name(2) }
ELSE {
WRITE !,"SQL error ",SQLCODE }
入力および出力のホスト変数の値の使用に関する制限については、"ホスト変数" を参照してください。
リテラル値および集約値を返すホスト変数
出力ホスト変数は SQLCODE=0 の場合にのみ有効であるため、SQLCODE=100 (クエリがテーブル・データを返しません) を発行するクエリの結果を使用しないようにすることが重要です。SQLCODE=100 の場合、すべての出力ホスト変数は既定で空文字列に設定されます。これには、返されるリテラルと COUNT 集約も含まれます。
以下の埋め込み SQL の例では、ホスト変数 (today) を SELECT 文に渡し、SELECT 文での計算によって INTO 節の変数値 (:tomorrow) が得られます。このホスト変数値は、包含するプログラムに渡されます。このクエリはテーブルのフィールドを参照しないため、FROM 節が指定されていません。FROM 節が指定されていない埋め込み SQL クエリは、SQLCODE=100 を発行できません。FROM 節が指定された埋め込み SQL クエリは、SQLCODE=100 を発行できます。SQLCODE=100 の場合、テーブルのフィールド値ではない :tomorrow など、すべての出力ホスト変数が既定の NULL 文字列値に定義されます。
SET today=$HOROLOG
&sql(SELECT :today+1
INTO :tomorrow )
IF SQLCODE=0 {
WRITE !,"Tomorrow is: ",$ZDATE(tomorrow) }
ELSE {
WRITE !,"SQL error ",SQLCODE }
以下の埋め込み SQL の例は、集約値を返します。この例では、COUNT 集約関数を使用してテーブルのレコードをカウントし、AVG を使用して Salary フィールド値の平均値を算出します。INTO 節は、これらの値を 2 つの添え字付きホスト変数として ObjectScript に返します。
どちらの select-items も集約なので、指定されたテーブルにデータが含まれていなくても、このプログラムは常に SQLCODE=0 を発行します。この場合、COUNT(*)=0 と AVG(Salary) が既定の空文字列になります。
WRITE !,"Counting the records"
&sql(SELECT COUNT(*),AVG(Salary)
INTO :agg(1),:agg(2)
FROM Sample.Employee)
IF SQLCODE=0 {
WRITE !,"Total Employee records= ",agg(1)
WRITE !,"Average Employee salary= ",agg(2) }
ELSEIF SQLCODE=100 {
WRITE !,"Total Employee records= ",agg(1) }
ELSE {
WRITE !,"SQL error ",SQLCODE }
以下の埋め込み SQL の例は前の例と同じですが、以下の例はフィールド値も返す点が異なります。select-items にフィールド値が含まれるので、指定されたテーブルにデータが含まれない場合、このプログラムは SQLCODE=100 を発行できます。この例では、SQLCODE=100 の場合、COUNT(*) は、0 ではなく既定の空文字列になります。
WRITE !,"Counting the records"
&sql(SELECT COUNT(*),AVG(Salary),Salary
INTO :agg(1),:agg(2),:pay
FROM Sample.Employee)
IF SQLCODE=0 {
WRITE !,"Total Employee records= ",agg(1)
WRITE !,"Average Employee salary= ",agg(2)
WRITE !,"Sample Employee salary=",pay }
ELSE {
WRITE !,"SQL error ",SQLCODE }
入力および出力のホスト変数の値の使用に関する制限については、"ホスト変数" を参照してください。
ホスト変数配列
以下の 2 つの埋め込み SQL の例では、ホスト変数配列を使用して、単一の行から非公開ではないデータ・フィールド値を返します。これらの例では、select-item リストで %ID が指定されています。これは、既定では SELECT * は RowId を返さないためです (ただし Sample.Person については RowID を返します)。RowID は常にフィールド 1 です。Sample.Person 内では、フィールド 4 および 9 は NULL を取ることができ、フィールド 5 はデータ・フィールドではなく (このフィールドは Sample.Address を参照します)、フィールド 10 は非公開です。
1 つ目の例では、指定された数のフィールドを返します (firstflds)。非公開のフィールドと非データ・フィールドは表示されませんが、この数に含まれます。多くのフィールドがあるテーブルから行を返す場合は、firstflds を使用することが適切です。この例は、親参照であるフィールド 0 を返すことができます。Sample.Person は子テーブルではないため、tflds(0) は未定義です。
&sql(SELECT *,%ID INTO :tflds()
FROM Sample.Person )
IF SQLCODE=0 {
SET firstflds=14
FOR i=0:1:firstflds {
IF $DATA(tflds(i)) {
WRITE "field ",i," = ",tflds(i),! }
} }
ELSE {WRITE "SQLCODE error=",SQLCODE,! }
2 つ目の例では、Sample.Person 内の非公開ではないすべてのデータ・フィールドを返します。Sample.Person 内で tflds(0) が未定義で、<UNDEFINED> エラーが発生するため、この例では、親参照であるフィールド 0 を返すことを試みません。
&sql(SELECT *,%ID INTO :tflds()
FROM Sample.Person )
IF SQLCODE=0 {
SET x=1
WHILE x '="" {
WRITE "field ",x," = ",tflds(x),!
SET x=$ORDER(tflds(x)) }
}
ELSE { WRITE "SQLCODE error=",SQLCODE,! }
以下の埋め込み SQL の例では、コンマ区切りのホスト変数リスト (非フィールド値用) とホスト変数配列 (フィールド値用) を組み合わせます。
&sql(SELECT %TABLENAME,Name,Age,AVG(Age)
INTO :tname,:tflds(),:ageavg
FROM Sample.Person
WHERE Age > 50 )
IF SQLCODE=0 {
WRITE "Table name is = ",tname,!
FOR i=0:1:25 {
IF $DATA(tflds(i)) {
WRITE "field ",i," = ",tflds(i),! }
}
WRITE "Average age is = ",ageavg,! }
ELSE {WRITE "SQLCODE=",SQLCODE,! }